home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ADA Programming Guide
/
ADA Programming Guide.iso
/
adatutor
/
lrmrdr
/
chap03.doc
< prev
next >
Wrap
Text File
|
1996-01-30
|
145KB
|
5,318 lines
The following document is a draft of the corresponding chapter of the
version of the Ada Reference Manual produced in response to the Ansi
Canvass. It is given a limited circulation to Ada implementers and to
other groups contributing comments (according to the conventions defined in
RRM.comments). This draft should not be referred to in any publication.
ANSI-RM-03-v23 - Draft Chapter
3 Declarations and Types
version 23
83-02-11
This version has addressed comments up to #5795
It has not yet considered the proposed amendment #3518
> 3. Declarations and Types
This chapter describes the types in the language and the rules for
declaring constants, variables, and named numbers.
> 3.1 Declarations
The language defines several kinds of entities that are declared, either
explicitly or implicitly, by declarations. Such an entity can be a numeric
literal, an object, a discriminant, a record component, a loop parameter,
an exception, a type, a subtype, a subprogram, a package, a task unit, a
generic unit, a single entry, an entry family, a formal parameter (of a
subprogram, entry, or generic subprogram), a generic formal parameter, a
named block or loop, a labeled statement, or an operation (in particular,
an attribute or an enumeration literal; see 3.3.3).
There are several forms of declaration. A basic declaration is a form of
declaration defined as follows.
basic_declaration ::=
object_declaration | number_declaration
| type_declaration | subtype_declaration
| subprogram_declaration | package_declaration
| task_declaration | generic_declaration
| exception_declaration | generic_instantiation
| renaming_declaration | deferred_constant_declaration
Certain forms of declaration always occur (explicitly) as part of a basic
declaration; these forms are discriminant specifications, component
declarations, entry declarations, parameter specifications, generic
parameter declarations, and enumeration literal specifications. A loop
parameter specification is a form of declaration that occurs only in
certain forms of loop statement.
The remaining forms of declaration are implicit: the name of a block, the
name of a loop, and a statement label are implicitly declared. Certain
operations are implicitly declared (see 3.3.3).
For each form of declaration the language rules define a certain region of
text called the scope of the declaration (see 8.2). Several forms of
declaration associate an identifier with a declared entity. Within its
scope, and only there, there are places where it is possible to use the
identifier to refer to the associated declared entity; these places are
defined by the visibility rules (see 8.3). At such places the identifier
is said to be a name of the entity (its simple name); the name is said to
denote the associated entity.
Certain forms of enumeration literal specification associate a character
literal with the corresponding declared entity. Certain forms of
declaration associate an operator symbol or some other notation with an
explicitly or implicitly declared operation.
The process by which a declaration achieves its effect is called the
elaboration of the declaration; this process happens during program
execution.
After its elaboration, a declaration is said to be elaborated. Prior to
the completion of its elaboration (including before the elaboration), the
declaration is not yet elaborated. The elaboration of any declaration has
always at least the effect of achieving this change of state (from not yet
elaborated to elaborated). The phrase "the elaboration has no other
effect" is used in this manual whenever this change of state is the only
effect of elaboration for some form of declaration. An elaboration process
is also defined for declarative parts, declarative items, and compilation
units (see 3.9 and 10.5).
Object, number, type, and subtype declarations are described here. The
remaining basic declarations are described in later chapters.
Note:
The syntax rules use the term identifier for the first occurrence of an
identifier in some form of declaration; the term simple name is used for
any occurrence of an identifier that already denotes some declared entity.
References: attribute 4.1.4, block name 5.6, block statement 5.6,
character literal 2.5, component declaration 3.7, declarative item 3.9,
declarative part 3.9, deferred constant declaration 7.4, discriminant
specification 3.7.1, elaboration 3.9, entry declaration 9.5, enumeration
literal specification 3.5.1, exception declaration 11.1, generic
declaration 12.1, generic instantiation 12.3, generic parameter declaration
12.1, identifier 2.3, label 5.1, loop name 5.5, loop parameter
specification 5.5, loop statement 5.5, name 4.1, number declaration 3.2.2,
numeric literal 2.4, object declaration 3.2.1, operation 3.3, operator
symbol 6.1, package declaration 7.1, parameter specification 6.1, record
component 3.7, renaming declaration 8.5, representation clause 13.1, scope
8.2, simple name 4.1, subprogram body 6.3, subprogram declaration 6.1,
subtype declaration 3.3.2, task declaration 9.1, type declaration 3.3.1,
visibility 8.3
> 3.2 Objects and Named Numbers
An object is an entity that contains (has) a value of a given type. An
object is one of the following:
- an object declared by an object declaration or by a single task
declaration,
- a formal parameter of a subprogram, entry, or generic subprogram,
- a generic formal object,
- a loop parameter,
- an object designated by a value of an access type,
- a component or a slice of another object.
A number declaration is a special form of object declaration that
associates an identifier with a value of type universal_integer or
universal_real.
object_declaration ::=
identifier_list : [constant] subtype_indication [:= expression];
| identifier_list : [constant] constrained_array_definition [:= expression];
number_declaration ::=
identifier_list : constant := universal_static_expression;
identifier_list ::= identifier {, identifier}
An object declaration is called a single object declaration if its
identifier list has a single identifier; it is called a multiple object
declaration if the identifier list has two or more identifiers. A multiple
object declaration is equivalent to a sequence of the corresponding number
of single object declarations. For each identifier of the list, the
equivalent sequence has a single object declaration formed by this
identifier, followed by a colon and by whatever appears at the right of the
colon in the multiple object declaration; the equivalent sequence is in
the same order as the identifier list.
A similar equivalence applies also for the identifier lists of number
declarations, component declarations, discriminant specifications,
parameter specifications, generic parameter declarations, exception
declarations, and deferred constant declarations.
In the remainder of this reference manual, explanations are given for
declarations with a single identifier; the corresponding explanations for
declarations with several identifiers follow from the equivalence stated
above.
Example:
-- the multiple object declaration
JOHN, PAUL : PERSON_NAME := new PERSON(SEX => M); -- see 3.8.1
-- is equivalent to the two single object declarations in the order given
JOHN : PERSON_NAME := new PERSON(SEX => M);
PAUL : PERSON_NAME := new PERSON(SEX => M);
References: access type 3.8, constrained array definition 3.6, component
3.3, declaration 3.1, deferred constant declaration 7.4, designate 3.8,
discriminant specification 3.7.1, entry 9.5, exception declaration 11.1,
expression 4.4, formal parameter 6.1, generic formal object 12.1.1, generic
parameter declaration 12.1, generic unit 12, generic subprogram 12.1,
identifier 2.3, loop parameter 5.5, numeric type 3.5, parameter
specification 6.1, scope 8.2, simple name 4.1, single task declaration 9.1,
slice 4.1.2, static expression 4.9, subprogram 6, subtype indication 3.3.2,
type 3.3, universal_integer type 3.5.4, universal_real type 3.5.6
> 3.2.1 Object Declarations
An object declaration declares an object whose type is given either by a
subtype indication or by a constrained array definition. If the object
declaration includes the assignment compound delimiter followed by an
expression, the expression specifies an initial value for the declared
object; the type of the expression must be that of the object.
The declared object is a constant if the reserved word constant appears in
the object declaration; the declaration must then include an explicit
initialization. The value of a constant cannot be modified after
initialization. Formal parameters of mode in of subprograms and entries,
and generic formal parameters of mode in, are also constants; a loop
parameter is a constant within the corresponding loop; a subcomponent or
slice of a constant is a constant.
An object that is not a constant is called a variable (in particular, the
object declared by an object declaration that does not include the reserved
word constant is a variable). The only ways to change the value of a
variable are either directly by an assignment, or indirectly when the
variable is updated (see 6.2) by a procedure or entry call statement (this
action can be performed either on the variable itself, on a subcomponent of
the variable, or on another variable that has the given variable as
subcomponent).
The elaboration of an object declaration proceeds as follows:
(a) The subtype indication or the constrained array definition is first
elaborated. This establishes the subtype of the object.
(b) If the object declaration includes an explicit initialization, the
initial value is obtained by evaluating the corresponding expression.
Otherwise any implicit initial values for the object or for its
subcomponents are evaluated.
(c) The object is created.
(d) Any initial value (whether explicit or implicit) is assigned to the
object or to the corresponding subcomponent.
Implicit initial values are defined for objects declared by object
declarations, and for components of such objects, in the following cases:
- If the type of an object is an access type, the implicit initial value
is the null value of the access type.
- If the type of an object is a task type, the implicit initial (and
only) value designates a corresponding task.
- If the type of an object is a type with discriminants and the subtype
of the object is constrained, the implicit initial (and only) value of
each discriminant is defined by the subtype of the object.
- If the type of an object is a composite type, the implicit initial
value of each component that has a default expression is obtained by
evaluation of this expression, unless the component is a discriminant
of a constrained object (the previous case).
In the case of a component that is itself a composite object and whose
value is defined neither by an explicit initialization nor by a default
expression, any implicit initial values for components of the composite
object are defined by the same rules as for a declared object.
The steps (a) to (d) are performed in the order indicated. For step (b),
if the default expression for a discriminant is evaluated, then this
evaluation is performed before that of default expressions for
subcomponents that depend on discriminants, and also before that of default
expressions that include the name of the discriminant. Apart from the
previous rule, the evaluation of default expressions is performed in some
order that is not defined by the language.
The initialization of an object (the declared object or one of its
subcomponents) checks that the initial value belongs to the subtype of the
object; for an array object declared by an object declaration, an implicit
subtype conversion is first applied as for an assignment statement, unless
the object is a constant whose subtype is an unconstrained array type. The
exception CONSTRAINT_ERROR is raised if this check fails.
The value of a scalar variable is undefined after elaboration of the
corresponding object declaration unless an initial value is assigned to the
variable by an initialization (explicitly or implicitly).
If the operand of a type conversion or qualified expression is a variable
that has scalar subcomponents with undefined values, then the values of the
corresponding subcomponents of the result are undefined. The execution of
a program is erroneous if it attempts to evaluate a scalar variable with
an undefined value. Similarly, the execution of a program is erroneous if
it attempts to apply a predefined operator to a variable that has a scalar
subcomponent with an undefined value.
Examples of variable declarations:
COUNT, SUM : INTEGER;
SIZE : INTEGER range 0 .. 10_000 := 0;
SORTED : BOOLEAN := FALSE;
COLOR_TABLE : array(1 .. N) of COLOR;
OPTION : BIT_VECTOR(1 .. 10) := (others => TRUE);
Examples of constant declarations:
LIMIT : constant INTEGER := 10_000;
LOW_LIMIT : constant INTEGER := LIMIT/10;
TOLERANCE : constant REAL := DISPERSION(1.15);
Note:
The expression initializing a constant object need not be a static
expression (see 4.9). In the above examples, LIMIT and LOW_LIMIT are
initialized with static expressions, but TOLERANCE is not if DISPERSION is
a user-defined function.
References: access type 3.8, assignment 5.2, assignment compound delimiter
5.2, component 3.3, composite type 3.3, constrained array definition 3.6,
constrained subtype 3.3, constraint_error exception 11.1, conversion 4.6,
declaration 3.1, default expression for a discriminant 3.7, default initial
value for an access type 3.8, depend on a discriminant 3.7.1, designate
3.8, discriminant 3.3, elaboration 3.9, entry 9.5, evaluation 4.5,
expression 4.4, formal parameter 6.1, generic formal parameter 12.1 12.3,
generic unit 12, in some order 1.6, limited type 7.4.4, mode in 6.1,
package 7, predefined operator 4.5, primary 4.4, private type 7.4,
qualified expression 4.7, reserved word 2.9, scalar type 3.5, slice 4.1.2,
subcomponent 3.3, subprogram 6, subtype 3.3, subtype indication 3.3.2, task
9, task type 9.2, type 3.3, visible part 7.2
> 3.2.2 Number Declarations
A number declaration is a special form of constant declaration. The type
of the static expression given for the initialization of a number
declaration must be either the type universal_integer or the type
universal_real. The constant declared by a number declaration is called a
named number and has the type of the static expression.
Note:
The rules concerning expressions of a universal type are explained in
section 4.10. It is a consequence of these rules that if every primary
contained in the expression is of the type universal_integer, then the
named number is also of this type. Similarly, if every primary is of the
type universal_real, then the named number is also of this type.
Examples of number declarations:
PI : constant := 3.14159_26536; -- a real number
TWO_PI : constant := 2.0*PI; -- a real number
MAX : constant := 500; -- an integer number
POWER_16 : constant := 2**16; -- the integer 65_536
ONE, UN, EINS : constant := 1; -- three different names for 1
References: identifier 2.3, primary 4.4, static expression 4.9, type 3.3,
universal_integer type 3.5.4, universal_real type 3.5.6, universal type
4.10
> 3.3 Types and Subtypes
A type is characterized by a set of values and a set of operations.
There exist several classes of types. Scalar types are integer types, real
types, and types defined by enumeration of their values; values of these
types have no components. Array and record types are composite; a value
of a composite type consists of component values. An access type is a type
whose values provide access to objects. Private types are types for which
the set of possible values is well defined, but not directly available to
the users of such types. Finally, there are task types. (Private types
are described in chapter 7, task types are described in chapter 9, the
other classes of types are described in this chapter.)
Certain record and private types have special components called
discriminants whose values distinguish alternative forms of values of one
of these types. If a private type has discriminants, they are known to
users of the type. Hence a private type is only known by its name, its
discriminants if any, and by the corresponding set of operations.
The set of possible values for an object of a given type can be subjected
to a condition that is called a constraint (the case where the constraint
imposes no restriction is also included); a value is said to satisfy a
constraint if it satisfies the corresponding condition. A subtype is a
type together with a constraint; a value is said to belong to a subtype of
a given type if it belongs to the type and satisfies the constraint; the
given type is called the base type of the subtype. A type is a subtype of
itself; such a subtype is said to be unconstrained: it corresponds to a
condition that imposes no restriction. The base type of a type is the type
itself.
The set of operations defined for a subtype of a given type includes the
operations that are defined for the type; however the assignment operation
to a variable having a given subtype only assigns values that belong to the
subtype. Additional operations, such as qualification (in a qualified
expression), are implicitly defined by a subtype declaration.
Certain types have default initial values defined for objects of the type;
certain other types have default expressions defined for some or all of
their components. Certain operations of types and subtypes are called
attributes; these operations are denoted by the form of name described in
section 4.1.4.
The term subcomponent is used in this manual in place of the term component
to indicate either a component, or a component of another component or
subcomponent. Where other subcomponents are excluded, the term component
is used instead.
A given type must not have a subcomponent whose type is the given type
itself.
The name of a class of types is used in this manual as a qualifier for
objects and values that have a type of the class considered. For example,
the term "array object" is used for an object whose type is an array type;
similarly, the term "access value" is used for a value of an access type.
Note:
The set of values of a subtype is a subset of the values of the base type.
This subset need not be a proper subset; it can be an empty subset.
References: access type 3.8, array type 3.6, assignment 5.2, attribute
4.1.4, component of an array 3.6, component of a record 3.7, discriminant
constraint 3.7.2, enumeration type 3.5.1, integer type 3.5.4, object 3.2.1,
private type 7.4, qualified expression 4.7, real type 3.5.6, record type
3.7, subtype declaration 3.3.2, task type 9.1, type declaration 3.3.1
> 3.3.1 Type Declarations
A type declaration declares a type.
type_declaration ::= full_type_declaration
| incomplete_type_declaration | private_type_declaration
full_type_declaration ::=
type identifier [discriminant_part] is type_definition;
type_definition ::=
enumeration_type_definition | integer_type_definition
| real_type_definition | array_type_definition
| record_type_definition | access_type_definition
| derived_type_definition
The elaboration of a full type declaration consists of the elaboration of
the discriminant part, if any (except in the case of the full type
declaration for an incomplete or private type declaration), and of the
elaboration of the type definition.
The types created by the elaboration of distinct type definitions are
distinct types. Moreover, the elaboration of the type definition for a
numeric or derived type creates both a base type and a subtype of the base
type; the same holds for a constrained array definition (one of the two
forms of array type definition).
The simple name declared by a full type declaration denotes the declared
type, unless the type declaration declares both a base type and a subtype
of the base type, in which case the simple name denotes the subtype, and
the base type is anonymous. A type is said to be anonymous if it has no
simple name. For explanatory purposes, this reference manual sometimes
refers to an anonymous type by a pseudo-name, written in italics, and uses
such pseudo-names at places where the syntax normally requires an
identifier.
Examples of type definitions:
(WHITE, RED, YELLOW, GREEN, BLUE, BROWN, BLACK)
range1 .. 72
array(1 .. 10) of INTEGER
Examples of type declarations:
type COLOR is (WHITE, RED, YELLOW, GREEN, BLUE, BROWN, BLACK);
type COLUMN is range 1 .. 72;
type TABLE is array(1 .. 10) of INTEGER;
Notes:
Two type definitions always define two distinct types, even if they are
textually identical. Thus, the array type definitions given in the
declarations of A and B below define distinct types.
A : array(1 .. 10) of BOOLEAN;
B : array(1 .. 10) of BOOLEAN;
If A and B are declared by a multiple object declaration as below, their
types are nevertheless different, since the multiple object declaration is
equivalent to the above two single object declarations.
A, B : array(1 .. 10) of BOOLEAN;
Incomplete type declarations are used for the definition of recursive and
mutually dependent types (see 3.8.1). Private type declarations are used
in package specifications and in generic parameter declarations (see 7.4
and 12.1).
References: access type definition 3.8, array type definition 3.6, base
type 3.3, constrained array definition 3.6, constrained subtype 3.3,
declaration 3.1, derived type 3.4, derived type definition 3.4,
discriminant part 3.7.1, elaboration 3.9, enumeration type definition
3.5.1, identifier 2.3, incomplete type declaration 3.8.1, integer type
definition 3.5.4, multiple object declaration 3.2, numeric type 3.5,
private type declaration 7.4, real type definition 3.5.6, reserved word
2.9, type 3.3
> 3.3.2 Subtype Declarations
A subtype declaration declares a subtype.
subtype_declaration ::=
subtype identifier is subtype_indication;
subtype_indication ::= type_mark [constraint]
type_mark ::= type_name | subtype_name
constraint ::=
range_constraint | floating_point_constraint | fixed_point_constraint
| index_constraint | discriminant_constraint
A type mark denotes a type or a subtype. If a type mark is the name of a
type, the type mark denotes this type and also the corresponding
unconstrained subtype. The base type of a type mark is, by definition, the
base type of the type or subtype denoted by the type mark.
A subtype indication defines a subtype of the base type of the type mark.
If an index constraint appears after a type mark in a subtype indication,
the type mark must not already impose an index constraint. Likewise for a
discriminant constraint, the type mark must not already impose a
discriminant constraint.
The elaboration of a subtype declaration consists of the elaboration of the
subtype indication. The elaboration of a subtype indication creates a
subtype. If the subtype indication does not include a constraint, the
subtype is the same as that denoted by the type mark. The elaboration of a
subtype indication that includes a constraint proceeds as follows:
(a) The constraint is first elaborated.
(b) A check is then made that the constraint is compatible with the type
or subtype denoted by the type mark.
The condition imposed by a constraint is the condition obtained after
elaboration of the constraint. (The rules of constraint elaboration are
such that the expressions and ranges of constraints are evaluated by the
elaboration of these constraints.) The rules defining compatibility are
given for each form of constraint in the appropriate section. These rules
are such that if a constraint is compatible with a subtype, then the
condition imposed by the constraint cannot contradict any condition already
imposed by the subtype on its values. The exception CONSTRAINT_ERROR is
raised if any check of compatibility fails.
Examples of subtype declarations:
subtype RAINBOW is COLOR range RED .. BLUE; -- see 3.3.1
subtype RED_BLUE is RAINBOW;
subtype INT is INTEGER;
subtype SMALL_INT is INTEGER range -10 .. 10;
subtype UP_TO_K is COLUMN range 1 .. K; -- see 3.3.1
subtype SQUARE is MATRIX(1 .. 10, 1 .. 10); -- see 3.6
subtype MALE is PERSON(SEX => M); -- see 3.8
Note:
A subtype declaration does not define a new type.
References: base type 3.3, compatibility of discriminant constraints
3.7.2, compatibility of fixed point constraints 3.5.9, compatibility of
floating point constraints 3.5.7, compatibility of index constraints 3.6.1,
compatibility of range constraints 3.5, constraint_error exception 11.1,
declaration 3.1, discriminant 3.3, discriminant constraint 3.7.2,
elaboration 3.9, evaluation 4.5, expression 4.4, floating point constraint
3.5.7, fixed point constraint 3.5.9, index constraint 3.6.1, range
constraint 3.5, reserved word 2.9, subtype 3.3, type 3.3, type name 3.3.1,
unconstrained subtype 3.3
> 3.3.3 Classification of Operations
The set of operations of a type includes the explicitly declared
subprograms that have a parameter or result of the type; such subprograms
are necessarily declared after the type declaration.
The remaining operations are each implicitly declared for a given type
declaration, immediately after the type definition. These implicitly
declared operations comprise the basic operations, the predefined operators
(see 4.5), and enumeration literals. In the case of a derived type
declaration, the implicitly declared operations include any derived
subprograms. The operations implicitly declared for a given type
declaration occur after the type declaration and before the next explicit
declaration, if any. The implicit declarations of derived subprograms
occur last.
A basic operation is an operation that is inherent in one of the following:
- An assignment (in assignment statements and initializations), an
allocator, a membership test, or a short-circuit control form.
- A selected component, an indexed component, or a slice.
- A qualification (in qualified expressions), an explicit type
conversion, or an implicit type conversion of a value of type
universal_integer or universal_real to the corresponding value of
another numeric type.
- A numeric literal (for a universal type), the literal null (for an
access type), a string literal, an aggregate, or an attribute.
For every type or subtype T, the following attribute is defined:
T'BASE The base type of T. This attribute is allowed only as the
prefix of the name of another attribute: for example,
T'BASE'FIRST.
Note:
Each literal is an operation whose evaluation yields the corresponding
value (see 4.2). Likewise, an aggregate is an operation whose evaluation
yields a value of a composite type (see 4.3). Some operations of a type
operate on values of the type, for example, predefined operators and
certain subprograms and attributes. The evaluation of some operations of a
type returns a value of the type, for example, literals and certain
functions, attributes, and predefined operators. Assignment is an
operation that operates on an object and a value. The evaluation of the
operation corresponding to a selected component, an indexed component, or a
slice, yields the object or value denoted by this form of name.
References: aggregate 4.3, allocator 4.8, assignment 5.2, attribute 4.1.4,
character literal 2.5, composite type 3.3, conversion 4.6, derived
subprogram 3.4, enumeration literal 3.5.1, formal parameter 6.1, function
6.5, indexed component 4.1.1, initial value 3.2.1, literal 4.2, membership
test 4.5 4.5.2, null literal 3.8, numeric literal 2.4, numeric type 3.5,
object 3.2.1, 6.1, predefined operator 4.5, qualified expression 4.7,
selected component 4.1.3, short-circuit control form 4.5 4.5.1, slice
4.1.2, string literal 2.6, subprogram 6, subtype 3.3, type 3.3, type
declaration 3.3.1, universal_integer type 3.5.4, universal_real type 3.5.6,
universal type 4.10
> 3.4 Derived Types
A derived type definition defines a new (base) type whose characteristics
are derived from those of a parent type; the new type is called a derived
type. A derived type definition further defines a derived subtype, which
is a subtype of the derived type.
derived_type_definition ::= new subtype_indication
The subtype indication that occurs after the reserved word new defines the
parent subtype. The parent type is the base type of the parent subtype.
If a constraint exists for the parent subtype, a similar constraint exists
for the derived subtype; the only difference is that for a range
constraint, and likewise for a floating or fixed point constraint that
includes a range constraint, the value of each bound is replaced by the
corresponding value of the derived type. The characteristics of the
derived type are defined as follows:
- The derived type belongs to the same class of types as the parent
type. The set of possible values for the derived type is a copy of
the set of possible values for the parent type. If the parent type is
composite, then the same components exist for the derived type, and
the subtype of corresponding components is the same.
- For each basic operation of the parent type, there is a corresponding
basic operation of the derived type. Explicit type conversion of a
value of the parent type into the corresponding value of the derived
type is allowed and vice versa as explained in section 4.6.
- For each enumeration literal or predefined operator of the parent type
there is a corresponding operation for the derived type.
- If the parent type is a task type, then for each entry of the parent
type there is a corresponding entry for the derived type.
- If a default expression exists for a component of an object having the
parent type, then the same default expression is used for the
corresponding component of an object having the derived type.
- If the parent type is an access type, then the parent and the derived
type share the same collection; there is a null access value for the
derived type and it is the default initial value of that type.
- If an explicit representation clause exists for the parent type and if
this clause appears before the derived type definition, then there is
a corresponding representation clause (an implicit one) for the
derived type.
- Certain subprograms that are operations of the parent type are said to
be derivable. For each derivable subprogram of the parent type, there
is a corresponding derived subprogram for the derived type. Two kinds
of derivable subprograms exist. First, if the parent type is declared
immediately within the visible part of a package, then a subprogram
that is itself explicitly declared immediately within the visible part
becomes derivable after the end of the visible part, if it is an
operation of the parent type. (The explicit declaration is by a
subprogram declaration, a renaming declaration, or a generic
instantiation.) Second, if the parent type is itself a derived type,
then any subprogram that has been derived by this parent type is
further derivable, unless the parent type is declared in the visible
part of a package and the derived subprogram is hidden by a derivable
subprogram of the first kind.
Each operation of the derived type is implicitly declared at the place of
the derived type declaration. The implicit declarations of any derived
subprograms occur last.
The specification of a derived subprogram is obtained implicitly by
systematic replacement of the parent type by the derived type in the
specification of the derivable subprogram. Any subtype of the parent type
is likewise replaced by a subtype of the derived type with a similar
constraint (as for the transformation of a constraint of the parent subtype
into the corresponding constraint of the derived subtype). Finally, any
expression of the parent type is made to be the operand of a type
conversion that yields a result of the derived type.
Calling a derived subprogram is equivalent to calling the corresponding
subprogram of the parent type, in which each actual parameter that is of
the derived type is replaced by a type conversion of this actual parameter
to the parent type (this means that a conversion to the parent type happens
before the call for the modes in and in out; a reverse conversion to the
derived type happens after the call for the modes in out and out, see
6.4.1). In addition, if the result of a called function is of the parent
type, this result is converted to the derived type.
If a derived or private type is declared immediately within the visible
part of a package, then, within this visible part, this type must not be
used as the parent type of a derived type definition. (For private types,
see also section 7.4.1.)
For the elaboration of a derived type definition, the subtype indication is
first elaborated, the derived type is then created, and finally, the
derived subtype is created.
Examples:
type LOCAL_COORDINATE is new COORDINATE; -- two different types
type MIDWEEK is new DAY range TUE .. THU; -- see 3.5.1
type COUNTER is new POSITIVE; -- same range as POSITIVE
type SPECIAL_KEY is new KEY_MANAGER.KEY; -- see 7.4.2
-- the derived subprograms have the following specifications:
-- procedure GET_KEY(K : out SPECIAL_KEY);
-- function "<"(X,Y : SPECIAL_KEY) return BOOLEAN;
Notes:
The rules of derivation of basic operations and enumeration literals imply
that the notation for any literal or aggregate of the derived type is the
same as for the parent type; such literals and aggregates are said to be
overloaded. Similarly, it follows that the notation for denoting a
component, a discriminant, an entry, a slice, or an attribute is the same
for the derived type as for the parent type.
Hiding of a derived subprogram is allowed even within the same declarative
region (see 8.3). A derived subprogram hides a predefined operator that
has the same parameter and result type profile (see 6.6).
A generic subprogram declaration is not derivable since it declares a
generic unit rather than a subprogram. On the other hand, an instantiation
of a generic subprogram is a (nongeneric) subprogram, which is derivable if
it satisfies the requirements for derivability of subprograms.
If the parent type is a boolean type, the predefined relational operators
of the derived type deliver a result of the predefined type BOOLEAN (see
4.5.2).
If a representation clause is given for the parent type but appears after
the derived type declaration, then no corresponding representation clause
applies to the derived type; hence an explicit representation clause for
such a derived type is allowed.
For a derived subprogram, if a parameter belongs to the derived type, the
subtype of this parameter need not have any value in common with the
derived subtype.
References: access value 3.8, actual parameter 6.4.1, aggregate 4.3,
attribute 4.1.4, base type 3.3, basic operation 3.3.3, boolean type 3.5.3,
bound of a range 3.5, class of type 3.3, collection 3.8, component 3.3,
composite type 3.3, constraint 3.3, conversion 4.6, declaration 3.1,
declarative region 8.1, default expression 3.2.1, default initial value for
an access type 3.8, discriminant 3.3, elaboration 3.9, entry 9.5,
enumeration literal 3.5.1, floating point constraint 3.5.7, fixed point
constraint 3.5.9, formal parameter 6.1, function call 6.4, generic
declaration 12.1, immediately within 8.1, implicit declaration 3.1, literal
4.2, mode 6.1, overloading 6.6 8.7, package 7, package specification 7.1,
parameter association 6.4, predefined operator 4.5, private type 7.4,
procedure 6, procedure call statement 6.4, range constraint 3.5,
representation clause 13.1, reserved word 2.9, slice 4.1.2, subprogram 6,
subprogram specification 6.1, subtype indication 3.3.2, subtype 3.3, type
3.3, type definition 3.3.1, visible part 7.2
> 3.5 Scalar Types
Scalar types comprise enumeration types, integer types, and real types.
Enumeration types and integer types are called discrete types; each value
of a discrete type has a position number which is an integer value.
Integer types and real types are called numeric types. All scalar types
are ordered, that is, all relational operators are predefined for their
values.
range_constraint ::= range range
range ::= range_attribute
| simple_expression .. simple_expression
A range specifies a subset of values of a scalar type. The range L .. R
specifies the values from L to R inclusive if the relation L <= R is true.
The values L and R are called the lower bound and upper bound of the range,
respectively. A value V is said to satisfy a range constraint if it
belongs to the range; the value V is said to belong to the range if the
relations L <= V and V <= R are both TRUE. A null range is a range for
which the relation R < L is TRUE; no value belongs to a null range. The
operators <= and < in the above definitions are the predefined operators of
the scalar type.
If a range constraint is used in a subtype indication, either directly or
as part of a floating or fixed point constraint, the type of the simple
expressions (likewise, of the bounds of a range attribute) must be the
same as the base type of the type mark of the subtype indication. A range
constraint is compatible with a subtype if each bound of the range belongs
to the subtype, or if the range constraint defines a null range; otherwise
the range constraint is not compatible with the subtype.
The elaboration of a range constraint consists of the evaluation of the
range. The evaluation of a range defines its lower bound and its upper
bound. If simple expressions are given to specify the bounds, the
evaluation of the range evaluates these simple expressions in some order
that is not defined by the language.
Attributes
For any scalar type T or for any subtype T of a scalar type, the following
attributes are defined:
T'FIRST Yields the lower bound of T. The value of this attribute has
the same type as T.
T'LAST Yields the upper bound of T. The value of this attribute has
the same type as T.
Note:
Indexing and iteration rules use values of discrete types.
References: attribute 4.1.4, constraint 3.3, enumeration type 3.5.1,
erroneous 1.6, evaluation 4.5, fixed point constraint 3.5.9, floating point
constraint 3.5.7, index 3.6, integer type 3.5.4, loop statement 5.5, range
attribute 3.6.2, real type 3.5.6, relational operator 4.5 4.5.2, satisfy a
constraint 3.3, simple expression 4.4, subtype indication 3.3.2, type mark
3.3.2
> 3.5.1 Enumeration Types
An enumeration type definition defines an enumeration type.
enumeration_type_definition ::=
(enumeration_literal_specification {, enumeration_literal_specification})
enumeration_literal_specification ::= enumeration_literal
enumeration_literal ::= identifier | character_literal
The identifiers and character literals listed by an enumeration type
definition must be distinct. Each enumeration literal specification is the
declaration of the corresponding enumeration literal: this declaration is
equivalent to the declaration of a parameterless function, the designator
being the enumeration literal, and the result type being the enumeration
type. The elaboration of an enumeration type definition creates an
enumeration type; this elaboration includes that of every enumeration
literal specification.
Each enumeration literal yields a different enumeration value. The
predefined order relations between enumeration values follow the order of
corresponding position numbers. The position number of the value of the
first listed enumeration literal is zero; the position number for each
other enumeration literal is one more than for its predecessor in the list.
If the same identifier or character literal is specified in more than one
enumeration type definition, the corresponding literals are said to be
overloaded. At any place where an overloaded enumeration literal occurs in
the text of a program, the type of the enumeration literal must be
determinable from the context (see 8.7).
Examples:
type DAY is (MON, TUE, WED, THU, FRI, SAT, SUN);
type SUIT is (CLUBS, DIAMONDS, HEARTS, SPADES);
type GENDER is (M, F);
type LEVEL is (LOW, MEDIUM, URGENT);
type COLOR is (WHITE, RED, YELLOW, GREEN, BLUE, BROWN, BLACK);
type LIGHT is (RED, AMBER, GREEN); -- RED and GREEN are overloaded
type HEXA is ('A', 'B', 'C', 'D', 'E', 'F');
type MIXED is ('A', 'B', '*', B, NONE, '?', '%');
subtype WEEKDAY is DAY range MON .. FRI;
subtype MAJOR is SUIT range HEARTS .. SPADES;
subtype RAINBOW is COLOR range RED .. BLUE; -- the color RED, not the light
Note:
If an enumeration literal occurs in a context that does not otherwise
suffice to determine the type of the literal, then qualification by the
name of the enumeration type is one way to resolve the ambiguity (see 8.7).
References: character literal 2.5, declaration 3.1, designator 6.1,
elaboration 3.9, 6.1, function 6.5, identifier 2.3, name 4.1, overloading
6.6 8.7, position number 3.5, qualified expression 4.7, relational operator
4.5 4.5.2, type 3.3, type definition 3.3.1
> 3.5.2 Character Types
An enumeration type is said to be a character type if at least one of its
enumeration literals is a character literal. The predefined type CHARACTER
is a character type whose values are the 128 characters of the ASCII
character set. Each of the 95 graphic characters of this character set is
denoted by the corresponding character literal.
Example:
type ROMAN_DIGIT is ('I', 'V', 'X', 'L', 'C', 'D', 'M');
Notes:
The predefined package ASCII includes the declaration of constants denoting
control characters and of constants denoting graphic characters that are
not in the basic character set.
A conventional character set such as EBCDIC can be declared as a character
type; the internal codes of the characters can be specified by an
enumeration representation clause as explained in section 13.3.
References: ascii predefined package C, basic character 2.1, character
literal 2.5, constant 3.2.1, declaration 3.1, enumeration type 3.5.1,
graphic character 2.1, identifier 2.3, literal 4.2, predefined type C, type
3.3
> 3.5.3 Boolean Types
There is a predefined enumeration type named BOOLEAN. It contains the two
literals FALSE and TRUE ordered with the relation FALSE < TRUE. A boolean
type is either the type BOOLEAN or a type that is derived, directly or
indirectly, from a boolean type.
References: derived type 3.4, enumeration literal 3.5.1, enumeration type
3.5.1, relational operator 4.5 4.5.2, type 3.3
> 3.5.4 Integer Types
An integer type definition defines an integer type whose set of values
includes at least those of the specified range.
integer_type_definition ::= range_constraint
If a range constraint is used as an integer type definition, each bound of
the range must be defined by a static expression of some integer type, but
the two bounds need not have the same integer type. (Negative bounds are
allowed.)
A type declaration of the form:
type T is range L .. R;
is, by definition, equivalent to the following declarations:
type integer_type is new predefined_integer_type;
subtype T is integer_type range integer_type(L) .. integer_type(R);
where integer_type is an anonymous type, and where the predefined integer
type is implicitly selected by the implementation, so as to contain the
values L to R inclusive. The integer type declaration is illegal if none
of the predefined integer types satisfies this requirement, excepting
universal_integer. The elaboration of the declaration of an integer type
consists of the elaboration of the equivalent type and subtype
declarations.
The predefined integer types include the type INTEGER. An implementation
may also have predefined types such as SHORT_INTEGER and LONG_INTEGER,
which have (substantially) shorter and longer ranges, respectively, than
INTEGER. The range of each of these types must be symmetric about zero,
excepting an extra negative value which may exist in some implementations.
The base type of each of these types is the type itself.
Integer literals are the literals of an anonymous predefined integer type
that is called universal_integer in this reference manual. Other integer
types have no literals. However, for each integer type there exists an
implicit conversion that converts a universal_integer value into the
corresponding value (if any) of the integer type. The circumstances under
which these implicit conversions are invoked are described in section 4.6.
The position number of an integer value is the corresponding value of the
type universal_integer.
The same arithmetic operators are predefined for all integer types (see
4.5). The exception NUMERIC_ERROR is raised by the execution of an
operation (in particular an implicit conversion) that cannot deliver the
correct result (that is, if the value corresponding to the mathematical
result is not a value of the integer type). However, an implementation is
not required to raise the exception NUMERIC_ERROR if the operation is part
of a larger expression whose result can be computed correctly, as described
in section 11.6.
Examples:
type PAGE_NUM is range 1 .. 2_000;
type LINE_SIZE is range 1 .. MAX_LINE_SIZE;
subtype SMALL_INT is INTEGER range -10 .. 10;
subtype COLUMN_PTR is LINE_SIZE range 1 .. 10;
subtype BUFFER_SIZE is INTEGER range 0 .. MAX;
Notes:
The name declared by an integer type declaration is a subtype name. On the
other hand, the predefined operators of an integer type deliver results
whose range is defined by the parent predefined type; such a result need
not belong to the declared subtype, in which case an attempt to assign the
result to a variable of the integer subtype raises the exception
CONSTRAINT_ERROR.
The smallest (most negative) value supported by the predefined integer
types of an implementation is the named number SYSTEM.MIN_INT and the
largest (most positive) value is SYSTEM.MAX_INT (see 13.7).
References: anonymous type 3.3.1, belong to a subtype 3.3, bound of a
range 3.5, constraint_error exception 11.1, conversion 4.6, identifier 2.3,
integer literal 2.4, literal 4.2, numeric_error exception 11.1, parent type
3.4, predefined operator 4.5, range constraint 3.5, static expression 4.9,
subtype declaration 3.3.2, system predefined package 13.7, type 3.3, type
declaration 3.3.1, type definition 3.3.1, universal type 4.10
> 3.5.5 Operations of Discrete Types
The basic operations of a discrete type include the operations involved in
assignment, the membership tests, and qualification; for a boolean type
they include the short-circuit control forms; for an integer type they
include the explicit conversion of values of other numeric types to the
integer type, and the implicit conversion of values of the type
universal_integer to the type.
Finally, for every discrete type or subtype T, the basic operations include
the attributes listed below. In this presentation, T is referred to as
being a subtype (the subtype T) for any property that depends on
constraints imposed by T; other properties are stated in terms of the base
type of T.
The first group of attributes yield characteristics of the subtype T. This
group includes the attribute BASE (see 3.3.2), the attributes FIRST and
LAST (see 3.5), the representation attribute SIZE (see 13.7.2), and the
attribute WIDTH defined as follows:
T'WIDTH Yields the maximum image length over all values of the subtype
T (the image is the sequence of characters returned by the
attribute IMAGE, see below). Yields zero for a null range.
The value of this attribute is of the type universal_integer.
All attributes of the second group are functions with a single parameter.
The corresponding actual parameter is indicated below by X.
T'POS This attribute is a function. The parameter X must be a value
of the base type of T. The result type is the type
universal_integer. The result is the position number of the
value of the parameter.
T'VAL This attribute is a special function with a single parameter
which can be of any integer type. The result type is the base
type of T. The result is the value whose position number is
the universal_integer value corresponding to X. The exception
CONSTRAINT_ERROR is raised if the universal_integer value
corresponding to X is not in the range T'POS(T'BASE'FIRST) ..
T'POS(T'BASE'LAST).
T'SUCC This attribute is a function. The parameter X must be a value
of the base type of T. The result type is the base type of T.
The result is the value whose position number is one greater
than that of X. The exception CONSTRAINT_ERROR is raised if X
equals T'BASE'LAST.
T'PRED This attribute is a function. The parameter X must be a value
of the base type of T. The result type is the base type of T.
The result is the value whose position number is one less than
that of X. The exception CONSTRAINT_ERROR is raised if X
equals T'BASE'FIRST.
T'IMAGE This attribute is a function. The parameter X must be a value
of the base type of T. The result type is the predefined type
STRING. The result is the image of the value of X, that is, a
sequence of characters representing the value in display form.
The image of an integer value is the corresponding decimal
literal; without underlines, leading zeros, exponent, or
trailing spaces; but with a single leading character that is
either a minus sign or a space. The lower bound of the image
is one.
The image of an enumeration value is either the corresponding
identifier in upper case or the corresponding character literal
(including the two apostrophes); neither leading nor trailing
spaces are included. The image of a character C, other than a
graphic character, is implementation-defined; the only
requirement is that the image must be such that C equals
CHARACTER'VALUE(CHARACTER'IMAGE(C)).
T'VALUE This attribute is a function. The parameter X must be a value
of the predefined type STRING. The result type is the base
type of T. Any leading and any trailing spaces of the sequence
of characters that corresponds to the parameter are ignored.
For an enumeration type, if the sequence of characters has the
syntax of an enumeration literal and if this literal exists for
the base type of T, the result is the corresponding enumeration
value. For an integer type, if the sequence of characters has
the syntax of an integer literal, with an optional single
leading character that is a plus or minus sign, and if there is
a corresponding value in the base type of T, the result is this
value. In any other case, the exception CONSTRAINT_ERROR is
raised.
In addition, the attributes A'SIZE and A'ADDRESS are defined for an object
A of a discrete type (see 13.7.2).
Besides the basic operations, the operations of a discrete type include the
predefined relational operators. For enumeration types, operations include
enumeration literals. For boolean types, operations include the predefined
unary logical negation operator not, and the predefined logical operators.
For integer types, operations include the predefined arithmetic operators:
these are the binary and unary adding operators - and +, all multiplying
operators, the unary operator abs, and the exponentiating operator.
The operations of a subtype are the corresponding operations of its base
type except for the following: assignment, membership tests,
qualification, explicit type conversions, and the attributes of the first
group; the effect of each of these operations depends on the subtype
(assignments, membership tests, qualifications, and conversions involve a
subtype check; attributes of the first group yield a characteristic of the
subtype).
Notes:
For a subtype of a discrete type, the results delivered by the attributes
SUCC, PRED, VAL, and VALUE need not belong to the subtype; similarly, the
actual parameters of the attributes POS, SUCC, PRED, and IMAGE need not
belong to the subtype. The following relations are satisfied (in the
absence of an exception) by these attributes:
T'POS(T'SUCC(X)) = T'POS(X) + 1
T'POS(T'PRED(X)) = T'POS(X) - 1
T'VAL(T'POS(X)) = X
T'POS(T'VAL(N)) = N
Examples:
-- For the types and subtypes declared in section 3.5.1 we have:
-- COLOR'FIRST = WHITE, COLOR'LAST = BLACK
-- RAINBOW'FIRST = RED, RAINBOW'LAST = BLUE
-- COLOR'SUCC(BLUE) = RAINBOW'SUCC(BLUE) = BROWN
-- COLOR'POS(BLUE) = RAINBOW'POS(BLUE) = 4
-- COLOR'VAL(0) = RAINBOW'VAL(0) = WHITE
References: abs operator 4.5 4.5.6, assignment 5.2, attribute 4.1.4, base
type 3.3, basic operation 3.3.3, binary adding operator 4.5 4.5.3, boolean
type 3.5.3, bound of a range 3.5, character literal 2.5, constraint 3.3,
constraint_error exception 11.1, conversion 4.6, discrete type 3.5,
enumeration literal 3.5.1, exponentiating operator 4.5 4.5.6, function 6.5,
graphic character 2.1, identifier 2.3, integer type 3.5.4, logical operator
4.5 4.5.1, membership test 4.5 4.5.2, multiplying operator 4.5 4.5.5, not
operator 4.5 4.5.6, numeric literal 2.4, numeric type 3.5, object 3.2,
operation 3.3, position number 3.5, predefined operator 4.5, predefined
type C, qualified expression 4.7, relational operator 4.5 4.5.2,
short-circuit control form 4.5 4.5.1, string type 3.6.3, subtype 3.3, type
3.3, unary adding operator 4.5 4.5.4, universal_integer type 3.5.4,
universal type 4.10
> 3.5.6 Real Types
Real types provide approximations to the real numbers, with relative bounds
on errors for floating point types, and with absolute bounds for fixed
point types.
real_type_definition ::=
floating_point_constraint | fixed_point_constraint
A set of numbers called model numbers is associated with each real type.
Error bounds on the predefined operations are given in terms of the model
numbers. An implementation of the type must include at least these model
numbers and represent them exactly.
An implementation-dependent set of numbers, called the safe numbers, is
also associated with each real type. The set of safe numbers of a real
type must include at least the set of model numbers of the type. The range
of safe numbers is allowed to be larger than the range of model numbers,
but error bounds on the predefined operations for safe numbers are given by
the same rules as for model numbers. Safe numbers therefore provide
guaranteed error bounds for operations on an implementation-dependent range
of numbers; in contrast, the range of model numbers depends only on the
real type definition and is therefore independent of the implementation.
Real literals are the literals of an anonymous predefined real type that is
called universal_real in this reference manual. Other real types have no
literals. However, for each real type, there exists an implicit conversion
that converts a universal_real value into a value of the real type. The
conditions under which these implicit conversions are invoked are described
in section 4.6. If the universal_real value is a safe number, the
implicit conversion delivers the corresponding value; if it belongs to the
range of safe numbers but is not a safe number, then the converted value
can be any value within the range defined by the safe numbers next above
and below the universal_real value.
The execution of an operation that yields a value of a real type may raise
the exception NUMERIC_ERROR, as explained in section 4.5.7, if it cannot
deliver a correct result (that is, if the value corresponding to one of the
possible mathematical results does not belong to the range of safe
numbers); in particular, this exception can be raised by an implicit
conversion. However, an implementation is not required to raise the
exception NUMERIC_ERROR if the operation is part of a larger expression
whose result can be computed correctly (see 11.6).
The elaboration of a real type definition includes the elaboration of the
floating or fixed point constraint and creates a real type.
Note:
An algorithm written to rely only upon the minimum numerical properties
guaranteed by the type definition for model numbers will be portable
without further precautions.
References: conversion 4.6, elaboration 3.9, fixed point constraint 3.5.9,
floating point constraint 3.5.7, literal 4.2, numeric_error exception 11.1,
predefined operation 3.3.3, real literal 2.4, type 3.3, type definition
3.3.1, universal type 4.10
> 3.5.7 Floating Point Types
For floating point types, the error bound is specified as a relative
precision by giving the required minimum number of significant decimal
digits.
floating_point_constraint ::=
floating_accuracy_definition [range_constraint]
floating_accuracy_definition ::= digits static_simple_expression
The minimum number of significant decimal digits is specified by the value
of the static simple expression of the floating accuracy definition. This
value must belong to some integer type and must be positive (nonzero); it
is denoted by D in the remainder of this section. If the floating point
constraint is used as a real type definition and includes a range
constraint, then each bound of the range must be defined by a static
expression of some real type, but the two bounds need not have the same
real type.
For a given radix, the following canonical form is defined for any floating
point model number other than zero:
sign * mantissa * (radix ** exponent)
In this form: sign is either +1 or -1; mantissa is expressed in a number
base given by radix; and exponent is an integer number (possibly negative)
such that the integer part of mantissa is zero and the first digit of its
fractional part is not a zero.
The specified number D is the minimum number of decimal digits required
after the point in the decimal mantissa (that is, if radix is ten). The
value of D in turn determines a corresponding number B that is the minimum
number of binary digits required after the point in the binary mantissa
(that is, if radix is two). The number B associated with D is the smallest
value such that the relative precision of the binary form is no less than
that specified for the decimal form. (The number B is the integer next
above (D*log(10)/log(2)) + 1.)
The model numbers defined by a floating accuracy definition comprise zero
and all numbers whose binary canonical form has exactly B digits after the
point in the mantissa and an exponent in the range -4*B .. +4*B. The
guaranteed minimum accuracy of operations of a floating point type is
defined in terms of the model numbers of the floating point constraint that
forms the corresponding real type definition (see 4.5.7).
The predefined floating point types include the type FLOAT. An
implementation may also have predefined types such as SHORT_FLOAT and
LONG_FLOAT, which have (substantially) less and more accuracy,
respectively, than FLOAT. The base type of each predefined floating point
type is the type itself. The model numbers of each predefined floating
point type are defined in terms of the number D of decimal digits returned
by the attribute DIGITS (see 3.5.8).
For each predefined floating point type (consequently also for each type
derived therefrom), a set of safe numbers is defined as follows. The safe
numbers have the same number B of mantissa digits as the model numbers of
the type and have an exponent in the range -E .. +E where E is
implementation-defined and at least equal to the 4*B of model numbers.
(Consequently, the safe numbers include the model numbers.) The rules
defining the accuracy of operations with model and safe numbers are given
in section 4.5.7. The safe numbers of a subtype are those of its base
type.
A floating point type declaration of one of the two forms (that is, with or
without the optional range constraint indicated by the square brackets):
type T is digits D [range L .. R];
is, by definition, equivalent to the following declarations:
type floating_point_type is new predefined_floating_point_type;
subtype T is floating_point_type digits D
[range floating_point_type(L) .. floating_point_type(R)];
where floating_point_type is an anonymous type, and where the predefined
floating point type is implicitly selected by the implementation so that
its model numbers include the model numbers defined by D; furthermore, if
a range L .. R is supplied, then both L and R must belong to the range of
safe numbers. The floating point declaration is illegal if none of the
predefined floating point types satisfies these requirements, excepting
universal_real. The maximum number of digits that can be specified in a
floating accuracy definition is given by the system-dependent named number
SYSTEM.MAX_DIGITS (see 13.7.1).
The elaboration of a floating point type declaration consists of the
elaboration of the equivalent type and subtype declarations.
If a floating point constraint follows a type mark in a subtype indication,
the type mark must denote a floating point type or subtype. The floating
point constraint is compatible with the type mark only if the number D
specified in the floating accuracy definition is not greater than the
corresponding number D for the type or subtype denoted by the type mark.
Furthermore, if the floating point constraint includes a range constraint,
the floating point constraint is compatible with the type mark only if the
range constraint is, itself, compatible with the type mark.
The elaboration of such a subtype indication includes the elaboration of
the range constraint, if there is one; it creates a floating point subtype
whose model numbers are defined by the corresponding floating accuracy
definition. A value of a floating point type belongs to a floating point
subtype if and only if it belongs to the range defined by the subtype.
The same arithmetic operators are predefined for all floating point types
(see 4.5).
Notes:
A range constraint is allowed in a floating point subtype indication,
either directly after the type mark, or as part of a floating point
constraint. In either case the bounds of the range must belong to the base
type of the type mark (see 3.5). The imposition of a floating point
constraint on a type mark in a subtype indication cannot reduce the allowed
range of values unless it includes a range constraint (the range of model
numbers that correspond to the specified number of digits can be smaller
than the range of numbers of the type mark). A value that belongs to a
floating point subtype need not be a model number of the subtype.
Examples:
type COEFFICIENT is digits 10 range -1.0 .. 1.0;
type REAL is digits 8;
type MASS is digits 7 range 0.0 .. 1.0E35;
subtype SHORT_COEFF is COEFFICIENT digits 5; -- a subtype with less accuracy
subtype PROBABILITY is REAL range 0.0 .. 1.0; -- a subtype with a smaller range
Notes on the examples:
The implemented accuracy for COEFFICIENT is that of a predefined type
having at least 10 digits of precision. Consequently the specification of
5 digits of precision for the subtype SHORT_COEFF is allowed. The largest
model number for the type MASS is approximately 1.27E30 and hence less than
the specified upper bound (1.0E35). Consequently the declaration of this
type is legal only if this upper bound is in the range of the safe numbers
of a predefined floating point type having at least 7 digits of precision.
References: anonymous type 3.3.1, arithmetic operator 3.5.5 4.5, based
literal 2.4.2, belong to a subtype 3.3, bound of a range 3.5, compatible
3.3.2, derived type 3.4, digit 2.1, elaboration 3.1 3.9, error bound 3.5.6,
exponent 2.4.1 integer type 3.5.4, model number 3.5.6, operation 3.3,
predefined operator 4.5, predefined type C, range constraint 3.5, real type
3.5.6, real type definition 3.5.6, safe number 3.5.6, simple expression
4.4, static expression 4.9, subtype declaration 3.3.2, subtype indication
3.3.2, subtype 3.3, type 3.3, type declaration 3.3.1, type mark 3.3.2
> 3.5.8 Operations of Floating Point Types
The basic operations of a floating point type include the operations
involved in assignment, membership tests, qualification, the explicit
conversion of values of other numeric types to the floating point type, and
the implicit conversion of values of the type universal_real to the type.
In addition, for every floating point type or subtype T, the basic
operations include the attributes listed below. In this presentation, T is
referred to as being a subtype (the subtype T) for any property that
depends on constraints imposed by T; other properties are stated in terms
of the base type of T.
The first group of attributes yield characteristics of the subtype T. The
attributes of this group are the attribute BASE (see 3.3.2), the attributes
FIRST and LAST (see 3.5), the representation attribute SIZE (see 13.7.2),
and the following attributes:
T'DIGITS Yields the number of decimal digits in the decimal mantissa of
model numbers of the subtype T. (This attribute yields the
number D of section 3.5.7.) The value of this attribute is of
the type universal_integer.
T'MANTISSA Yields the number of binary digits in the binary mantissa of
model numbers of the subtype T. (This attribute yields the
number B of section 3.5.7.) The value of this attribute is of
the type universal_integer.
T'EPSILON Yields the absolute value of the difference between the model
number 1.0 and the next model number above, for the subtype T.
The value of this attribute is of the type universal_real.
T'EMAX Yields the largest exponent value in the binary canonical form
of model numbers of the subtype T. (This attribute yields the
product 4*B of section 3.5.7.) The value of this attribute is
of the type universal_integer.
T'SMALL Yields the smallest positive (nonzero) model number of the
subtype T. The value of this attribute is of the type
universal_real.
T'LARGE Yields the largest positive model number of the subtype T.
The value of this attribute is of the type universal_real.
The attributes of the second group include the following attributes which
yield characteristics of the safe numbers:
T'SAFE_EMAX Yields the largest exponent value in the binary canonical form
of safe numbers of the base type of T. (This attribute yields
the number E of section 3.5.7.) The value of this attribute
is of the type universal_integer.
T'SAFE_SMALL Yields the smallest positive (nonzero) safe number of the base
type of T. The value of this attribute is of the type
universal_real.
T'SAFE_LARGE Yields the largest positive safe number of the base type of T.
The value of this attribute is of the type universal_real.
In addition, the attributes A'SIZE and A'ADDRESS are defined for an object
A of a floating point type (see 13.7.2). Finally, for each floating point
type there are machine-dependent attributes that are not related to model
numbers and safe numbers. They correspond to the attribute designators
MACHINE_RADIX, MACHINE_MANTISSA, MACHINE_EMAX, MACHINE_EMIN,
MACHINE_ROUNDS, and MACHINE_OVERFLOWS (see 13.7.3).
Besides the basic operations, the operations of a floating point type
include the relational operators, and the following predefined arithmetic
operators: the binary and unary adding operators - and +, the multiplying
operators * and /, the unary operator abs, and the exponentiating operator.
The operations of a subtype are the corresponding operations of the type
except for the following: assignment, membership tests, qualification,
explicit conversion, and the attributes of the first group; the effects of
these operations are redefined in terms of the subtype.
Notes:
The attributes EMAX, SMALL, LARGE, and EPSILON are provided for
convenience. They are all related to MANTISSA by the following formulas:
T'EMAX = 4*T'MANTISSA
T'EPSILON = 2.0**(1 - T'MANTISSA)
T'SMALL = 2.0**(-T'EMAX - 1)
T'LARGE = 2.0**T'EMAX * (1.0 - 2.0**(-T'MANTISSA))
The attribute MANTISSA, giving the number of binary digits in the mantissa,
is itself related to DIGITS. The following relations hold between the
characteristics of the model numbers and those of the safe numbers:
T'BASE'EMAX <= T'SAFE_EMAX
T'BASE'SMALL >= T'SAFE_SMALL
T'BASE'LARGE <= T'SAFE_LARGE
The attributes T'FIRST and T'LAST need not yield model or safe numbers. If
a certain number of digits is specified in the declaration of a type or
subtype T, the attribute T'DIGITS yields this number.
References: abs operator 4.5 4.5.6, arithmetic operator 3.5.5 4.5,
assignment 5.2, attribute 4.1.4, base type 3.3, basic operation 3.3.3,
binary adding operator 4.5 4.5.3, bound of a range 3.5, constraint 3.3,
conversion 4.6, digit 2.1, exponentiating operator 4.5 4.5.6, floating
point type 3.5.7, membership test 4.5 4.5.2, model number 3.5.6,
multiplying operator 4.5 4.5.5, numeric type 3.5, object 3.2, operation
3.3, predefined operator 4.5, qualified expression 4.7, relational operator
4.5 4.5.2, safe number 3.5.6, subtype 3.3, type 3.3, unary adding operator
4.5 4.5.4, universal type 4.10, universal_integer type 3.5.4,
universal_real type 3.5.6
> 3.5.9 Fixed Point Types
For fixed point types, the error bound is specified as an absolute value,
called the delta of the fixed point type.
fixed_point_constraint ::=
fixed_accuracy_definition [range_constraint]
fixed_accuracy_definition ::= delta static_simple_expression
The delta is specified by the value of the static simple expression of the
fixed accuracy definition. This value must belong to some real type and
must be positive (nonzero). If the fixed point constraint is used as a
real type definition, then it must include a range constraint; each bound
of the specified range must be defined by a static expression of some real
type but the two bounds need not have the same real type. If the fixed
point constraint is used in a subtype indication, the range constraint is
optional.
A canonical form is defined for any fixed point model number other than
zero. In this form: sign is either +1 or -1; mantissa is a positive
(nonzero) integer; and any model number is a multiple of a certain
positive real number called small, as follows:
sign * mantissa * small
For the model numbers defined by a fixed point constraint, the number small
is chosen as the largest power of two that is not greater than the delta of
the fixed accuracy definition. Alternatively, it is possible to specify
the value of small by a length clause (see 13.2), in which case model
numbers are multiples of the specified value. The guaranteed minimum
accuracy of operations of a fixed point type is defined in terms of the
model numbers of the fixed point constraint that forms the corresponding
real type definition (see 4.5.7).
For a fixed point constraint that includes a range constraint, the model
numbers comprise zero and all multiples of small whose mantissa can be
expressed using exactly B binary digits, where the value of B is chosen as
the smallest integer number for which each bound of the specified range is
either a model number or lies at most small distant from a model number.
For a fixed point constraint that does not include a range constraint (this
is only allowed after a type mark, in a subtype indication), the model
numbers are defined by the delta of the fixed accuracy definition and by
the range of the subtype denoted by the type mark.
An implementation must have at least one anonymous predefined fixed point
type. The base type of each such fixed point type is the type itself. The
model numbers of each predefined fixed point type comprise zero and all
numbers for which mantissa (in the canonical form) has the number of binary
digits returned by the attribute MANTISSA, and for which the number small
has the value returned by the attribute SMALL.
A fixed point type declaration of the form:
type T is delta D range L .. R;
is, by definition, equivalent to the following declarations:
type fixed_point_type is new predefined_fixed_point_type;
subtype T is fixed_point_type
range fixed_point_type(L) .. fixed_point_type(R);
In these declarations, fixed_point_type is an anonymous type, and the
predefined fixed point type is implicitly selected by the implementation so
that its model numbers include the model numbers defined by the fixed point
constraint (that is, by D, L, and R, and possibly by a length clause
specifying small).
The fixed point declaration is illegal if no predefined type satisfies
these requirements. The safe numbers of a fixed point type are the model
numbers of its base type.
The elaboration of a fixed point type declaration consists of the
elaboration of the equivalent type and subtype declarations.
If the fixed point constraint follows a type mark in a subtype indication,
the type mark must denote a fixed point type or subtype. The fixed point
constraint is compatible with the type mark only if the delta specified by
the fixed accuracy definition is not smaller than the delta for the type or
subtype denoted by the type mark. Furthermore, if the fixed point
constraint includes a range constraint, the fixed point constraint is
compatible with the type mark only if the range constraint is, itself,
compatible with the type mark.
The elaboration of such a subtype indication includes the elaboration of
the range constraint, if there is one; it creates a fixed point subtype
whose model numbers are defined by the corresponding fixed point constraint
and also by the length clause specifying small, if there is one. A value
of a fixed point type belongs to a fixed point subtype if and only if it
belongs to the range defined by the subtype.
The same arithmetic operators are predefined for all fixed point types (see
4.5). Multiplication and division of fixed point values deliver results of
an anonymous predefined fixed point type that is called universal_fixed in
this reference manual; the accuracy of this type is arbitrarily fine. The
values of this type must be converted explicitly to some numeric type.
Notes:
If S is a subtype of a fixed point type or subtype T, then the set of model
numbers of S is a subset of those of T. If a length clause has been given
for T, then both S and T have the same value for small. Otherwise, since
small is a power of two, the small of S is equal to the small of T
multiplied by a nonnegative power of two.
A range constraint is allowed in a fixed point subtype indication, either
directly after the type mark, or as part of a fixed point constraint. In
either case the bounds of the range must belong to the base type of the
type mark (see 3.5).
Examples:
type VOLT is delta 0.125 range 0.0 .. 255.0;
subtype ROUGH_VOLTAGE is VOLT delta 1.0; -- same range as VOLT
-- A pure fraction which requires all the available space in a word
-- on a two's complement machine can be declared as the type FRACTION:
DEL : constant := 1.0/2**(WORD_LENGTH - 1);
type FRACTION is delta DEL range -1.0 .. 1.0 - DEL;
References: anonymous type 3.3.1, arithmetic operator 3.5.5 4.5, base type
3.3, belong to a subtype 3.3, bound of a range 3.5, compatible 3.3.2,
conversion 4.6, elaboration 3.9, error bound 3.5.6, length clause 13.2,
model number 3.5.6, numeric type 3.5, operation 3.3, predefined operator
4.5, range constraint 3.5, real type 3.5.6, real type definition 3.5.6,
safe number 3.5.6, simple expression 4.4, static expression 4.9, subtype
3.3, subtype declaration 3.3.2, subtype indication 3.3.2, type 3.3, type
declaration 3.3.1, type mark 3.3.2
> 3.5.10 Operations of Fixed Point Types
The basic operations of a fixed point type include the operations involved
in assignment, membership tests, qualification, the explicit conversion of
values of other numeric types to the fixed point type, and the implicit
conversion of values of the type universal_real to the type.
In addition, for every fixed point type or subtype T the basic operations
include the attributes listed below. In this presentation T is referred to
as being a subtype (the subtype T) for any property that depends on
constraints imposed by T; other properties are stated in terms of the base
type of T.
The first group of attributes yield characteristics of the subtype T. The
attributes of this group are the attributes BASE (see 3.3.2), the
attributes FIRST and LAST (see 3.5), the representation attribute SIZE (see
13.7.2) and the following attributes:
T'DELTA Yields the value of the delta specified in the fixed accuracy
definition for the subtype T. The value of this attribute is
of the type universal_real.
T'MANTISSA Yields the number of binary digits in the mantissa of model
numbers of the subtype T. (This attribute yields the number B
of section 3.5.9.) The value of this attribute is of the type
universal_integer.
T'SMALL Yields the smallest positive (nonzero) model number of the
subtype T. The value of this attribute is of the type
universal_real.
T'LARGE Yields the largest positive model number of the subtype T.
The value of this attribute is of the type universal_real.
T'FORE Yields the minimum number of characters needed for the integer
part of the decimal representation of any value of the subtype
T, assuming that the representation does not include an
exponent, but includes a one-character prefix that is either a
minus sign or a space. (This minimum number does not include
superfluous zeros or underlines, and is at least two.) The
value of this attribute is of the type universal_integer.
T'AFT Yields the number of decimal digits needed after the point to
accommodate the precision of the subtype T, unless the delta
of the subtype T is greater than 0.1, in which case the
attribute yields the value one. (T'AFT is the smallest
positive integer N for which (10**N)*T'DELTA is greater than
or equal to one.) The value of this attribute is of the type
universal_integer.
The attributes of the second group include the following attributes which
yield characteristics of the safe numbers:
T'SAFE_SMALL Yields the smallest positive (nonzero) safe number of the base
type of T. The value of this attribute is of the type
universal_real.
T'SAFE_LARGE Yields the largest positive safe number of the base type of T.
The value of this attribute is of the type universal_real.
In addition, the attributes A'SIZE and A'ADDRESS are defined for an object
A of a fixed point type (see 13.7.2). Finally, for each fixed point type
or subtype T, there are the machine-dependent attributes T'MACHINE_ROUNDS
and T'MACHINE_OVERFLOWS (see 13.7.3).
Besides the basic operations, the operations of a fixed point type include
the relational operators, and the following predefined arithmetic
operators: the binary and unary adding operators - and +, the multiplying
operators * and /, and the operator abs.
The operations of a subtype are the corresponding operations of the type
except for the following: assignment, membership tests, qualification,
explicit conversion, and the attributes of the first group; the effects of
these operations are redefined in terms of the subtype.
Notes:
The value of the attribute T'FORE depends only on the range of the subtype
T. The value of the attribute T'AFT depends only on the value of T'DELTA.
The following relations exist between attributes of a fixed point type:
T'LARGE = (2**T'MANTISSA - 1) * T'SMALL
T'SAFE_LARGE = T'BASE'LARGE
T'SAFE_SMALL = T'BASE'SMALL
References: abs operator 4.5 4.5.6, arithmetic operator 3.5.5 4.5,
assignment 5.2, base type 3.3, basic operation 3.3.3, binary adding
operator 4.5 4.5.3, bound of a range 3.5, conversion 4.6, delta 3.5.9,
fixed point type 3.5.9, membership test 4.5 4.5.2, model number 3.5.6,
multiplying operator 4.5 4.5.5, numeric type 3.5, object 3.2, operation
3.3, qualified expression 4.7, relational operator 4.5 4.5.2, safe number
3.5.6, subtype 3.3, unary adding operator 4.5 4.5.4, universal_integer type
3.5.4, universal_real type 3.5.6
> 3.6 Array Types
An array object is a composite object consisting of components that have
the same subtype. The name for a component of an array uses one or more
index values belonging to specified discrete types. The value of an array
object is a composite value consisting of the values of its components.
array_type_definition ::=
unconstrained_array_definition | constrained_array_definition
unconstrained_array_definition ::=
array(index_subtype_definition {, index_subtype_definition}) of
component_subtype_indication
constrained_array_definition ::=
array index_constraint of component_subtype_indication
index_subtype_definition ::= type_mark range <>
index_constraint ::= (discrete_range {, discrete_range})
discrete_range ::= discrete_subtype_indication | range
An array object is characterized by the number of indices (the
dimensionality of the array), the type and position of each index, the
lower and upper bounds for each index, and the type and possible constraint
of the components. The order of the indices is significant.
A one-dimensional array has a distinct component for each possible index
value. A multidimensional array has a distinct component for each possible
sequence of index values that can be formed by selecting one value for
each index position (in the given order). The possible values for a given
index are all the values between the lower and upper bounds, inclusive;
this range of values is called the index range.
An unconstrained array definition defines an array type. For each object
that has the array type, the number of indices, the type and position of
each index, and the subtype of the components are as in the type
definition; the values of the lower and upper bounds for each index belong
to the corresponding index subtype, except for null arrays as explained in
section 3.6.1. The index subtype for a given index position is, by
definition, the subtype denoted by the type mark of the corresponding index
subtype definition. The compound delimiter <> (called a box) of an index
subtype definition stands for an undefined range (different objects of the
type need not have the same bounds). The elaboration of an unconstrained
array definition creates an array type; this elaboration includes that of
the component subtype indication.
A constrained array definition defines both an array type and a subtype of
this type:
- The array type is an implicitly declared anonymous type; this type is
defined by an (implicit) unconstrained array definition, in which the
component subtype indication is that of the constrained array
definition, and in which the type mark of each index subtype
definition denotes the subtype defined by the corresponding discrete
range.
- The array subtype is the subtype obtained by imposition of the index
constraint on the array type.
If a constrained array definition is given for a type declaration, the
simple name declared by this declaration denotes the array subtype.
The elaboration of a constrained array definition creates the corresponding
array type and array subtype. For this elaboration, the index constraint
and the component subtype indication are elaborated. The evaluation of
each discrete range of the index constraint and the elaboration of the
component subtype indication are performed in some order that is not
defined by the language.
Examples of type declarations with unconstrained array definitions:
type VECTOR is array(INTEGER range <>) of REAL;
type MATRIX is array(INTEGER range <>, INTEGER range <>) of REAL;
type BIT_VECTOR is array(INTEGER range <>) of BOOLEAN;
type ROMAN is array(POSITIVE range <>) of ROMAN_DIGIT;
Examples of type declarations with constrained array definitions:
type TABLE is array(1 .. 10) of INTEGER;
type SCHEDULE is array(DAY) of BOOLEAN;
type LINE is array(1 .. MAX_LINE_SIZE) of CHARACTER;
Examples of object declarations with constrained array definitions:
GRID : array(1 .. 80, 1 .. 100) of BOOLEAN;
MIX : array(COLOR range RED .. GREEN) of BOOLEAN;
PAGE : array(1 .. 50) of LINE; -- an array of arrays
Note:
For a one-dimensional array, the rule given means that a type declaration
with a constrained array definition such as
type T is array(POSITIVE range MIN .. MAX) of COMPONENT;
is equivalent (in the absence of an incorrect order dependence) to the
succession of declarations
subtype INDEX_SUBTYPE is POSITIVE range MIN .. MAX;
type ARRAY_TYPE is array(INDEX_SUBTYPE range <>) of COMPONENT;
subtype T is ARRAY_TYPE(INDEX_SUBTYPE);
where index_subtype and array_type are both anonymous. Consequently, T is
the name of a subtype and all objects declared with this type mark are
arrays that have the same bounds. Similar transformations apply to
multidimensional arrays.
A similar transformation applies to an object whose declaration includes a
constrained array definition. A consequence of this is that no two such
objects have the same type.
References: anonymous type 3.3.1, bound of a range 3.5, component 3.3,
constraint 3.3, discrete type 3.5, elaboration 3.1 3.9, in some order 1.6,
name 4.1, object 3.2, range 3.5, subtype 3.3, subtype indication 3.3.2,
type 3.3, type declaration 3.3.1, type definition 3.3.1, type mark 3.3.2
> 3.6.1 Index Constraints and Discrete Ranges
An index constraint determines the range of possible values for every index
of an array type, and thereby the corresponding array bounds.
For a discrete range used in a constrained array definition and defined by
a range, an implicit conversion to the predefined type INTEGER is assumed
if each bound is either a numeric literal, a named number, or an attribute,
and the type of both bounds (prior to the implicit conversion) is the type
universal_integer. Otherwise, both bounds must be of the same discrete
type, other than universal_integer; this type must be determinable
independently of the context, but using the fact that the type must be
discrete and that both bounds must have the same type. These rules apply
also to a discrete range used in an iteration rule (see 5.5) or in the
declaration of a family of entries (see 9.5).
If an index constraint follows a type mark in a subtype indication, then
the type or subtype denoted by the type mark must not already impose an
index constraint. The type mark must denote either an unconstrained array
type or an access type whose designated type is such an array type. In
either case, the index constraint must provide a discrete range for each
index of the array type and the type of each discrete range must be the
same as that of the corresponding index.
An index constraint is compatible with the type denoted by the type mark if
and only if the constraint defined by each discrete range is compatible
with the corresponding index subtype. If any of the discrete ranges
defines a null range, any array thus constrained is a null array, having no
components. An array value satisfies an index constraint if at each index
position the array value and the index constraint have the same index
bounds. (Note, however, that assignment and certain other operations on
arrays involve an implicit subtype conversion.)
The bounds of each array object are determined as follows:
- For a variable declared by an object declaration, the subtype
indication of the corresponding object declaration must define a
constrained array subtype (and, thereby, the bounds). The same
requirement exists for the subtype indication of a component
declaration, if the type of the record component is an array type;
and for the component subtype indication of an array type definition,
if the type of the array components is itself an array type.
- For a constant declared by an object declaration, the bounds of the
constant are defined by the initial value if the subtype of the
constant is unconstrained; they are otherwise defined by this subtype
(in the latter case, the initial value is the result of an implicit
subtype conversion). The same rule applies to a generic formal
parameter of mode in.
- For an array object designated by an access value, the bounds must be
defined by the allocator that creates the array object. (The
allocated object is constrained with the corresponding values of the
bounds.)
- For a formal parameter of a subprogram or entry, the bounds are
obtained from the corresponding actual parameter. (The formal
parameter is constrained with the corresponding values of the bounds.)
- For a renaming declaration and for a generic formal parameter of mode
in out, the bounds are those of the renamed object or of the
corresponding generic actual parameter.
For the elaboration of an index constraint, the discrete ranges are
evaluated in some order that is not defined by the language.
Examples of array declarations including an index constraint:
BOARD : MATRIX(1 .. 8, 1 .. 8); -- see 3.6
RECTANGLE : MATRIX(1 .. 20, 1 .. 30);
INVERSE : MATRIX(1 .. N, 1 .. N); -- N need not be static
FILTER : BIT_VECTOR(0 .. 31);
Example of array declaration with a constrained array subtype:
MY_SCHEDULE : SCHEDULE; -- all arrays of type SCHEDULE have the same bounds
Example of record type with a component that is an array:
type VAR_LINE(LENGTH : INTEGER) is
record
IMAGE : STRING(1 .. LENGTH);
end record;
NULL_LINE : VAR_LINE(0); -- NULL_LINE.IMAGE is a null array
Notes:
The elaboration of a subtype indication consisting of a type mark followed
by an index constraint checks the compatibility of the index constraint
with the type mark (see 3.3.2).
All components of an array have the same subtype. In particular, for an
array of components that are one-dimensional arrays, this means that all
components have the same bounds and hence the same length.
References: access type 3.8, access type definition 3.8, access value 3.8,
actual parameter 6.4.1, allocator 4.8, array bound 3.6, array component
3.6, array type 3.6, array type definition 3.6, bound of a range 3.5,
compatible 3.3.2, component declaration 3.7, constant 3.2.1, constrained
array definition 3.6, constrained array subtype 3.6, conversion 4.6,
designate 3.8, designated type 3.8, discrete range 3.6, entry 9.5, entry
family declaration 9.5, expression 4.4, formal parameter 6.1, function 6.5,
generic actual parameter 12.3, generic formal parameter 12.1 12.3, generic
parameter 12.1, index 3.6, index constraint 3.6.1, index subtype 3.6,
initial value 3.2.1, integer literal 2.4, integer type 3.5.4, iteration
rule 5.5, mode 12.1.1, name 4.1, null range 3.5, object 3.2, object
declaration 3.2.1, predefined type C, range 3.5, record component 3.7,
renaming declaration 8.5, result subtype 6.1, satisfy 3.3, subprogram 6,
subtype conversion 4.6, subtype indication 3.3.2, type mark 3.3.2,
unconstrained array type 3.6, unconstrained subtype 3.3, universal type
4.10, universal_integer type 3.5.4, variable 3.2.1
> 3.6.2 Operations of Array Types
The basic operations of an array type include the operations involved in
assignment and aggregates (unless the array type is limited), membership
tests, indexed components, qualification, and explicit conversion; for
one-dimensional arrays the basic operations also include the operations
involved in slices, and also string literals if the component type is a
character type.
If A is an array object, an array value, or a constrained array subtype,
the basic operations also include the attributes listed below. These
attributes are not allowed for an unconstrained array type. The argument N
used in the attribute designators for the N-th dimension of an array must
be a static expression of type universal_integer. The value of N must be
positive (nonzero) and no greater than the dimensionality of the array.
A'FIRST Yields the lower bound of the first index range. The value
of this attribute has the same type as this lower bound.
A'FIRST(N) Yields the lower bound of the N-th index range. The value
of this attribute has the same type as this lower bound.
A'LAST Yields the upper bound of the first index range. The value
of this attribute has the same type as this upper bound.
A'LAST(N) Yields the upper bound of the N-th index range. The value
of this attribute has the same type as this upper bound.
A'RANGE Yields the first index range, that is, the range A'FIRST ..
A'LAST.
A'RANGE(N) Yields the N-th index range, that is, the range A'FIRST(N)
.. A'LAST(N).
A'LENGTH Yields the number of values of the first index range (zero
for a null range). The value of this attribute is of the
type universal_integer.
A'LENGTH(N) Yields the number of values of the N-th index range (zero
for a null range). The value of this attribute is of the
type universal_integer.
In addition, the attribute T'BASE is defined for an array type or subtype T
(see 3.3.3); the attribute T'SIZE is defined for an array type or subtype
T, and the attributes A'SIZE and A'ADDRESS are defined for an array object
A (see 13.7.2).
Besides the basic operations, the operations of an array type include the
predefined comparison for equality and inequality, unless the array type is
limited. For one-dimensional arrays, the operations include catenation,
unless the array type is limited; if the component type is a discrete
type, the operations also include all predefined relational operators; if
the component type is a boolean type, then the operations also include the
unary logical negation operator not, and the logical operators.
Examples (using arrays declared in the examples of section 3.6.1):
-- FILTER'FIRST = 0 FILTER'LAST = 31 FILTER'LENGTH = 32
-- RECTANGLE'LAST(1) = 20 RECTANGLE'LAST(2) = 30
Notes:
The attributes A'FIRST and A'FIRST(1) yield the same value. A similar
relation exists for the attributes A'LAST, A'RANGE, and A'LENGTH. The
following relations are satisfied (except for a null array) by the above
attributes if the index type is an integer type:
A'LENGTH = A'LAST - A'FIRST + 1
A'LENGTH(N) = A'LAST(N) - A'FIRST(N) + 1
An array type is limited if its component type is limited (see 7.4.4).
References: aggregate 4.3, array type 3.6, assignment 5.2, attribute
4.1.4, basic operation 3.3.3, bound of a range 3.5, catenation operator 4.5
4.5.3, character type 3.5.2, constrained array subtype 3.6, conversion 4.6,
designator 6.1, dimension 3.6, index 3.6, indexed component 4.1.1, limited
type 7.4.4, logical operator 4.5 4.5.1, membership test 4.5 4.5.2, not
operator 4.5 4.5.6, null range 3.5, object 3.2, operation 3.3, predefined
operator 4.5, qualified expression 4.7, relational operator 4.5 4.5.2,
slice 4.1.2, static expression 4.9, string literal 2.6, subcomponent 3.3,
type 3.3, unconstrained array type 3.6, universal type 4.10,
universal_integer type 3.5.4
> 3.6.3 The Type String
The values of the predefined type STRING are one-dimensional arrays of the
predefined type CHARACTER, indexed by values of the predefined subtype
POSITIVE:
subtype POSITIVE is INTEGER range 1 .. INTEGER'LAST;
type STRING is array(POSITIVE range <>) of CHARACTER;
Examples:
STARS : STRING(1 .. 120) := (1 .. 120 => '*' );
QUESTION : constant STRING := "HOW MANY CHARACTERS?";
-- QUESTION'FIRST = 1, QUESTION'LAST = 20 (the number of characters)
ASK_TWICE : constant STRING := QUESTION & QUESTION;
NINETY_SIX : constant ROMAN := "XCVI"; -- see 3.6
Notes:
String literals (see 2.6 and 4.2) are basic operations applicable to the
type STRING and to any other one-dimensional array type whose component
type is a character type. The catenation operator is a predefined operator
for the type STRING and for one-dimensional array types; it is represented
as &. The relational operators <, <=, >, and >= are defined for values of
these types, and correspond to lexicographic order (see 4.5.2).
References: aggregate 4.3, array 3.6, catenation operator 4.5 4.5.3,
character type 3.5.2, component type (of an array) 3.6, dimension 3.6,
index 3.6, lexicographic order 4.5.2, positional aggregate 4.3, predefined
operator 4.5, predefined type C, relational operator 4.5 4.5.2, string
literal 2.6, subtype 3.3, type 3.3
> 3.7 Record Types
A record object is a composite object consisting of named components. The
value of a record object is a composite value consisting of the values of
its components.
record_type_definition ::=
record
component_list
end record
component_list ::=
component_declaration {component_declaration}
| {component_declaration} variant_part
| null;
component_declaration ::=
identifier_list : component_subtype_definition [:= expression];
component_subtype_definition ::= subtype_indication
Each component declaration declares a component of the record type.
Besides components declared by component declarations, the components of a
record type include any components declared by discriminant specifications
of the record type declaration. The identifiers of all components of a
record type must be distinct. The use of a name that denotes a record
component other than a discriminant is not allowed within the record type
definition that declares the component.
A component declaration with several identifiers is equivalent to a
sequence of single component declarations, as explained in section 3.2.
Each single component declaration declares a record component whose subtype
is specified by the component subtype definition.
If a component declaration includes the assignment compound delimiter
followed by an expression, the expression is the default expression of the
record component; the default expression must be of the type of the
component. Default expressions are not allowed for components that are of
a limited type.
If a record type does not have a discriminant part, the same components are
present in all values of the type. If the component list of a record type
is defined by the reserved word null and there is no discriminant part,
then the record type has no components and all records of the type are null
records.
The elaboration of a record type definition creates a record type; it
consists of the elaboration of any corresponding (single) component
declarations, in the order in which they appear, including any component
declaration in a variant part. The elaboration of a component declaration
consists of the elaboration of the component subtype definition.
For the elaboration of a component subtype definition, if the constraint
does not depend on a discriminant (see 3.7.1), then the subtype indication
is elaborated. If, on the other hand, the constraint depends on a
discriminant, then the elaboration consists of the evaluation of any
included expression that is not a discriminant.
Examples of record type declarations:
type DATE is
record
DAY : INTEGER range 1 .. 31;
MONTH : MONTH_NAME;
YEAR : INTEGER range 0 .. 4000;
end record;
type COMPLEX is
record
RE : REAL := 0.0;
IM : REAL := 0.0;
end record;
Examples of record variables:
TOMORROW, YESTERDAY : DATE;
A, B, C : COMPLEX;
-- both components of A, B, and C are implicitly initialized to zero
Notes:
The default expression of a record component is implicitly evaluated by the
elaboration of the declaration of a record object, in the absence of an
explicit initialization (see 3.2.1). If a component declaration has
several identifiers, the expression is evaluated once for each such
component of the object (since the declaration is equivalent to a sequence
of single component declarations).
Unlike the components of an array, the components of a record need not be
of the same type.
References: assignment compound delimiter 2.2, component 3.3, composite
value 3.3, constraint 3.3, declaration 3.1, depend on a discriminant 3.7.1,
discriminant 3.3, discriminant part 3.7 3.7.1, elaboration 3.9, expression
4.4, identifier 2.3, identifier list 3.2, limited type 7.4.4, name 4.1,
object 3.2, subtype 3.3, type 3.3, type mark 3.3.2, variant part 3.7.3
> 3.7.1 Discriminants
A discriminant part specifies the discriminants of a type. A discriminant
of a record is a component of the record. The type of a discriminant must
be discrete.
discriminant_part ::=
(discriminant_specification {; discriminant_specification})
discriminant_specification ::=
identifier_list : type_mark [:= expression]
A discriminant part is only allowed in the type declaration for a record
type, in a private type declaration or an incomplete type declaration (the
corresponding full declaration must then declare a record type), and in the
generic parameter declaration for a formal private type.
A discriminant specification with several identifiers is equivalent to a
sequence of single discriminant specifications, as explained in section
3.2. Each single discriminant specification declares a discriminant. If a
discriminant specification includes the assignment compound delimiter
followed by an expression, the expression is the default expression of the
discriminant; the default expression must be of the type of the
discriminant. Default expressions must be provided either for all or for
none of the discriminants of a discriminant part.
The use of the name of a discriminant is not allowed in default expressions
of a discriminant part if the specification of the discriminant is itself
given in the discriminant part.
Within a record type definition the only allowed uses of the name of a
discriminant of the record type are: in the default expressions for record
components; in a variant part as the discriminant name; and in a
component subtype definition, either as a bound in an index constraint, or
to specify a discriminant value in a discriminant constraint. A
discriminant name used in these component subtype definitions must appear
by itself, not as part of a larger expression. Such component subtype
definitions and such constraints are said to depend on a discriminant.
A component is said to depend on a discriminant if it is a record component
declared in a variant part, or a record component whose component subtype
definition depends on a discriminant, or finally, one of the subcomponents
of a component that itself depends on a discriminant.
Each record value includes a value for each discriminant specified for the
record type; it also includes a value for each record component that does
not depend on a discriminant. The values of the discriminants determine
which other component values are in the record value.
Direct assignment to a discriminant of an object is not allowed;
furthermore a discriminant is not allowed as an actual parameter of mode in
out or out, or as a generic actual parameter of mode in out. The only
allowed way to change the value of a discriminant of a variable is to
assign a (complete) value to the variable itself. Similarly, an assignment
to the variable itself is the only allowed way to change the constraint of
one of its components, if the component subtype definition depends on a
discriminant of the variable.
The elaboration of a discriminant part has no other effect.
Examples:
type BUFFER(SIZE : BUFFER_SIZE := 100) is -- see 3.5.4
record
POS : BUFFER_SIZE := 0;
VALUE : STRING(1 .. SIZE);
end record;
type SQUARE(SIDE : INTEGER) is
record
MAT : MATRIX(1 .. SIDE, 1 .. SIDE); -- see 3.6
end record;
type DOUBLE_SQUARE(NUMBER : INTEGER) is
record
LEFT : SQUARE(NUMBER);
RIGHT : SQUARE(NUMBER);
end record;
type ITEM(NUMBER : POSITIVE) is
record
CONTENT : INTEGER;
-- no component depends on the discriminant
end record;
References: assignment 5.2, assignment compound delimiter 2.2, bound of a
range 3.5, component 3.3, component declaration 3.7, component of a record
3.7, declaration 3.1, discrete type 3.5, discriminant 3.3, discriminant
constraint 3.7.2, elaboration 3.9, expression 4.4, generic formal type
12.1, generic parameter declaration 12.1, identifier 2.3, identifier list
3.2, incomplete type declaration 3.8.1, index constraint 3.6.1, name 4.1,
object 3.2, private type 7.4, private type declaration 7.4, record type
3.7, scope 8.2, simple name 4.1, subcomponent 3.3, subtype indication
3.3.2, type declaration 3.3.1, type mark 3.3.2, variant part 3.7.3
> 3.7.2 Discriminant Constraints
A discriminant constraint is only allowed in a subtype indication, after a
type mark. This type mark must denote either a type with discriminants, or
an access type whose designated type is a type with discriminants. A
discriminant constraint specifies the values of these discriminants.
discriminant_constraint ::=
(discriminant_association {, discriminant_association})
discriminant_association ::=
[discriminant_simple_name {| discriminant_simple_name} =>] expression
Each discriminant association associates an expression with one or more
discriminants. A discriminant association is said to be named if the
discriminants are specified explicitly by their names; it is otherwise
said to be positional. For a positional association, the (single)
discriminant is implicitly specified by position, in textual order. Named
associations can be given in any order, but if both positional and named
associations are used in the same discriminant constraint, then positional
associations must occur first, at their normal position. Hence once a
named association is used, the rest of the discriminant constraint must use
only named associations.
For a named discriminant association, the discriminant names must denote
discriminants of the type for which the discriminant constraint is given.
A discriminant association with more than one discriminant name is only
allowed if the named discriminants are all of the same type. Furthermore,
for each discriminant association (whether named or positional), the
expression and the associated discriminants must have the same type. A
discriminant constraint must provide exactly one value for each
discriminant of the type.
A discriminant constraint is compatible with the type denoted by a type
mark, if and only if each discriminant value belongs to the subtype of the
corresponding discriminant. In addition, for each subcomponent whose
component subtype specification depends on a discriminant, the
discriminant value is substituted for the discriminant in this component
subtype specification and the compatibility of the resulting subtype
indication is checked.
A composite value satisfies a discriminant constraint if and only if each
discriminant of the composite value has the value imposed by the
discriminant constraint.
The initial values of the discriminants of an object of a type with
discriminants are determined as follows:
- For a variable declared by an object declaration, the subtype
indication of the corresponding object declaration must impose a
discriminant constraint unless default expressions exist for the
discriminants; the discriminant values are defined either by the
constraint or, in its absence, by the default expressions. The same
requirement exists for the subtype indication of a component
declaration, if the type of the record component has discriminants;
and for the component subtype indication of an array type, if the type
of the array components is a type with discriminants.
- For a constant declared by an object declaration, the values of the
discriminants are those of the initial value if the subtype of the
constant is unconstrained; they are otherwise defined by this subtype
(in the latter case, an exception is raised if the initial value does
not belong to this subtype). The same rule applies to a generic
parameter of mode in.
- For an object designated by an access value, the discriminant values
must be defined by the allocator that creates the object. (The
allocated object is constrained with the corresponding discriminant
values.)
- For a formal parameter of a subprogram or entry, the discriminants of
the formal parameter are initialized with those of the corresponding
actual parameter. (The formal parameter is constrained if the
corresponding actual parameter is constrained, and in any case if the
mode is in or if the subtype of the formal parameter is constrained.)
- For a renaming declaration and for a generic formal parameter of mode
in out, the discriminants are those of the renamed object or of the
corresponding generic actual parameter.
For the elaboration of a discriminant constraint, the expressions given in
the discriminant associations are evaluated in some order that is not
defined by the language; the expression of a named association is
evaluated once for each named discriminant.
Examples (using types declared in the previous section):
LARGE : BUFFER(200); -- constrained, always 200 characters (explicit discriminant value)
MESSAGE : BUFFER; -- unconstrained, initially 100 characters (default discriminant value)
BASIS : SQUARE(5); -- constrained, always 5 by 5
ILLEGAL : SQUARE; -- illegal, a SQUARE must be constrained
Note:
The above rules and the rules defining the elaboration of an object
declaration (see 3.2) ensure that discriminants always have a value. In
particular, if a discriminant constraint is imposed on an object
declaration, each discriminant is initialized with the value specified by
the constraint. Similarly, if the subtype of a component has a
discriminant constraint, the discriminants of the component are
correspondingly initialized.
References: access type 3.8, access type definition 3.8, access value 3.8,
actual parameter 6.4.1, allocator 4.8, array type definition 3.6, bound of
a range 3.5, compatible 3.3.2, component 3.3, component declaration 3.7,
component subtype indication 3.7, composite value 3.3, constant 3.2.1,
constrained subtype 3.3, constraint 3.3, declaration 3.1, default
expression for a discriminant 3.7, depend on a discriminant 3.7.1,
designate 3.8, designated type 3.8, discriminant 3.3, elaboration 3.9,
entry 9.5, evaluation 4.5, expression 4.4, formal parameter 6.1, generic
actual parameter 12.3, generic formal parameter 12.1 12.3, mode in 6.1,
mode in out 6.1, name 4.1, object 3.2, object declaration 3.2.1, renaming
declaration 8.5, reserved word 2.9, satisfy 3.3, simple name 4.1,
subcomponent 3.3, subprogram 6, subtype 3.3, subtype indication 3.3.2, type
3.3, type mark 3.3.2, variable 3.2.1
> 3.7.3 Variant Parts
A record type with a variant part specifies alternative lists of
components. Each variant defines the components for the corresponding
value or values of the discriminant.
variant_part ::=
case discriminant_simple_name is
variant
{variant}
end case;
variant ::=
when choice {| choice} =>
component_list
choice ::= simple_expression
| discrete_range | others | component_simple_name
Each variant starts with a list of choices which must be of the same type
as the discriminant of the variant part. The type of the discriminant of a
variant part must not be a generic formal type. If the subtype of the
discriminant is static, then each value of this subtype must be represented
once and only once in the set of choices of the variant part, and no other
value is allowed. Otherwise, each value of the (base) type of the
discriminant must be represented once and only once in the set of choices.
The simple expressions and discrete ranges given as choices in a variant
part must be static. A choice defined by a discrete range stands for all
values in the corresponding range (none if a null range). The choice
others is only allowed for the last variant and as its only choice; it
stands for all values (possibly none) not given in the choices of previous
variants. A component simple name is not allowed as a choice of a variant
(although it is part of the syntax of choice).
A record value contains the values of the components of a given variant if
and only if the discriminant value is equal to one of the values specified
by the choices of the variant. This rule applies in turn to any further
variant that is, itself, included in the component list of the given
variant. If the component list of a variant is specified by null, the
variant has no components.
Example of record type with a variant part:
type DEVICE is (PRINTER, DISK, DRUM);
type STATE is (OPEN, CLOSED);
type PERIPHERAL(UNIT : DEVICE := DISK) is
record
STATUS : STATE;
case UNIT is
when PRINTER =>
LINE_COUNT : INTEGER range 1 .. PAGE_SIZE;
when others =>
CYLINDER : CYLINDER_INDEX;
TRACK : TRACK_NUMBER;
end case;
end record;
Examples of record subtypes:
subtype DRUM_UNIT is PERIPHERAL(DRUM);
subtype DISK_UNIT is PERIPHERAL(DISK);
Examples of constrained record variables:
WRITER : PERIPHERAL(UNIT => PRINTER);
ARCHIVE : DISK_UNIT;
Note:
Choices with discrete values are also used in case statements and in array
aggregates. Choices with component simple names are used in record
aggregates.
References: array aggregate 4.3.2, base type 3.3, component 3.3, component
list 3.7, discrete range 3.6, discriminant 3.3, generic formal type 12.1.2,
null range 3.5, record aggregate 4.3.1, range 3.5, record type 3.7, simple
expression 4.4, simple name 4.1, static discrete range 4.9, static
expression 4.9, static subtype 4.9, subtype 3.3
> 3.7.4 Operations of Record Types
The basic operations of a record type include the operations involved in
assignment and aggregates (unless the type is limited), membership tests,
selection of record components, qualification, and type conversion (for
derived types).
For any object A of a type with discriminants, the basic operations also
include the following attribute:
A'CONSTRAINED Yields the value TRUE if a discriminant constraint applies
to the object A, or if the object is a constant (including
a formal parameter or generic formal parameter of mode in);
yields the value FALSE otherwise. If A is a generic formal
parameter of mode in out, or if A is a formal parameter of
mode in out or out and the type mark given in the
corresponding parameter specification denotes an
unconstrained type with discriminants, then the value of
this attribute is obtained from that of the corresponding
actual parameter. The value of this attribute is of the
predefined type BOOLEAN.
In addition, the attributes T'BASE and T'SIZE are defined for a record type
or subtype T (see 3.3.3); the attributes A'SIZE and A'ADDRESS are defined
for a record object A (see 13.7.2).
Besides the basic operations, the operations of a record type include the
predefined comparison for equality and inequality, unless the type is
limited.
Note:
A record type is limited if the type of any of its components is limited
(see 7.4.4).
References: actual parameter 6.4.1, aggregate 4.3, assignment 5.2,
attribute 4.1.4, basic operation 3.3.3, boolean type 3.5.3, constant 3.2.1,
conversion 4.6, derived type 3.4, discriminant 3.3, discriminant constraint
3.7.2, formal parameter 6.1, generic actual parameter 12.3, generic formal
parameter 12.1 12.3, limited type 7.4.4, membership test 4.5 4.5.2, mode
6.1, object 3.2.1, operation 3.3, predefined operator 4.5, predefined type
C, qualified expression 4.7, record type 3.7, relational operator 4.5
4.5.2, selected component 4.1.3, subcomponent 3.3, subtype 3.3, type 3.3
> 3.8 Access Types
An object declared by an object declaration is created by the elaboration
of the object declaration and is denoted by a simple name or by some other
form of name. In contrast, there are objects that are created by the
evaluation of allocators (see 4.8) and that have no simple name. Access to
such an object is achieved by an access value returned by an allocator;
the access value is said to designate the object.
access_type_definition ::= access subtype_indication
For each access type, there is a literal null which has a null access value
designating no object at all. The null value of an access type is the
default initial value of the type. Other values of an access type are
obtained by evaluation of a special operation of the type, called an
allocator. Each such access value designates an object of the subtype
defined by the subtype indication of the access type definition; this
subtype is called the designated subtype; the base type of this subtype is
called the designated type. The objects designated by the values of an
access type form a collection implicitly associated with the type.
The elaboration of an access type definition consists of the elaboration of
the subtype indication and creates an access type.
If an access object is constant, the contained access value cannot be
changed and always designates the same object. On the other hand, the
value of the designated object need not remain the same (assignment to the
designated object is allowed unless the designated type is limited).
The only forms of constraint that are allowed after the name of an access
type in a subtype indication are index constraints and discriminant
constraints. (See sections 3.6.1 and 3.7.2 for the rules applicable to
these subtype indications.) An access value belongs to a corresponding
subtype of an access type either if the access value is the null value or
if the value of the designated object satisfies the constraint.
Examples:
type FRAME is access MATRIX; -- see 3.6
type BUFFER_NAME is access BUFFER; -- see 3.7.1
Notes:
An access value delivered by an allocator can be assigned to several access
objects. Hence it is possible for an object created by an allocator to be
designated by more than one variable or constant of the access type. An
access value can only designate an object created by an allocator; in
particular, it cannot designate an object declared by an object
declaration.
If the type of the objects designated by the access values is an array type
or a type with discriminants, these objects are constrained with either the
array bounds or the discriminant values supplied implicitly or explicitly
for the corresponding allocators (see 4.8).
Access values are called pointers or references in some other languages.
References: allocator 4.8, array type 3.6, assignment 5.2, belong to a
subtype 3.3, constant 3.2.1, constraint 3.3, discriminant constraint 3.7.2,
elaboration 3.9, index constraint 3.6.1, index specification 3.6, limited
type 7.4.4, literal 4.2, name 4.1, object 3.2.1, object declaration 3.2.1,
reserved word 2.9, satisfy 3.3, simple name 4.1, subcomponent 3.3, subtype
3.3, subtype indication 3.3.2, type 3.3, variable 3.2.1
> 3.8.1 Incomplete Type Declarations
There are no particular limitations on the designated type of an access
type. In particular, the type of a component of the designated type can be
another access type, or even the same access type. This permits mutually
dependent and recursive access types. Their declarations require a prior
incomplete (or private) type declaration for one or more types.
incomplete_type_declaration ::= type identifier [discriminant_part];
For each incomplete type declaration, there must be a corresponding
declaration of a type with the same identifier. The corresponding
declaration must be either a full type declaration or the declaration of a
task type. In the rest of this section, explanations are given in terms of
full type declarations; the same rules apply also to declarations of task
types. If the incomplete type declaration occurs immediately within either
a declarative part or the visible part of a package specification, then the
full type declaration must occur later and immediately within this
declarative part or visible part. If the incomplete type declaration
occurs immediately within the private part of a package, then the full type
declaration must occur later and immediately within either the private part
itself, or the declarative part of the corresponding package body.
A discriminant part must be given in the full type declaration if and only
if one is given in the incomplete type declaration; if discriminant parts
are given, then they must conform (see 6.3.1 for the conformance rules).
Prior to the end of the full type declaration, the only allowed use of a
name that denotes a type declared by an incomplete type declaration is as
the type mark in the subtype indication of an access type definition; the
only form of constraint allowed in this subtype indication is a
discriminant constraint.
The elaboration of an incomplete type declaration creates a type. If the
incomplete type declaration has a discriminant part, this elaboration
includes that of the discriminant part: in such a case, the discriminant
part of the full type declaration is not elaborated.
Example of a recursive type:
type CELL; -- incomplete type declaration
type LINK is access CELL;
type CELL is
record
VALUE : INTEGER;
SUCC : LINK;
PRED : LINK;
end record;
HEAD : LINK := new CELL'(0, null, null);
NEXT : LINK := HEAD.SUCC;
Examples of mutually dependent access types:
type PERSON(SEX : GENDER); -- incomplete type declaration
type CAR; -- incomplete type declaration
type PERSON_NAME is access PERSON;
type CAR_NAME is access CAR;
type CAR is
record
NUMBER : INTEGER;
OWNER : PERSON_NAME;
end record;
type PERSON(SEX : GENDER) is
record
NAME : STRING(1 .. 20);
BIRTH : DATE;
AGE : INTEGER range 0 .. 130;
VEHICLE : CAR_NAME;
case SEX is
when M => WIFE : PERSON_NAME(SEX => F);
when F => HUSBAND : PERSON_NAME(SEX => M);
end case;
end record;
MY_CAR, YOUR_CAR, NEXT_CAR : CAR_NAME; -- implicitly initialized with null value
References: access type 3.8, access type definition 3.8, component 3.3,
conform 6.3.1, constraint 3.3, declaration 3.1, declarative item 3.9,
designate 3.8, discriminant constraint 3.7.2, discriminant part 3.7.1,
elaboration 3.9, identifier 2.3, name 4.1, subtype indication 3.3.2, type
3.3, type mark 3.3.2
> 3.8.2 Operations of Access Types
The basic operations of an access type include the operations involved in
assignment, allocators for the access type, membership tests,
qualification, explicit conversion, and the literal null. If the
designated type is a type with discriminants, the basic operations include
the selection of the corresponding discriminants; if the designated type
is a record type, they include the selection of the corresponding
components; if the designated type is an array type, they include the
formation of indexed components and slices; if the designated type is a
task type, they include selection of entries and entry families.
Furthermore, the basic operations include the formation of a selected
component with the reserved word all (see 4.1.3).
If the designated type is an array type, the basic operations include the
attributes that have the attribute designators FIRST, LAST, RANGE, and
LENGTH (likewise, the attribute designators of the N-th dimension). The
prefix of each of these attributes must be a value of the access type.
These attributes yield the corresponding characteristics of the designated
object (see 3.6.2).
If the designated type is a task type, the basic operations include the
attributes that have the attribute designators TERMINATED and CALLABLE (see
9.9). The prefix of each of these attributes must be a value of the access
type. These attributes yield the corresponding characteristics of the
designated task objects.
In addition, the attribute T'BASE (see 3.3.3) and the representation
attributes T'SIZE and T'STORAGE_SIZE (see 13.7.2) are defined for an access
type or subtype T; the attributes A'SIZE and A'ADDRESS are defined for an
access object A (see 13.7.2).
Besides the basic operations, the operations of an access type include the
predefined comparison for equality and inequality.
References: access type 3.8, allocator 4.8, array type 3.6, assignment
5.2, attribute 4.1.4, attribute designator 4.1.4, base type 3.3, basic
operation 3.3.3, collection 3.8, constrained array subtype 3.6, conversion
4.6, designate 3.8, designated subtype 3.8, designated type 3.8,
discriminant 3.3, indexed component 4.1.1, literal 4.2, membership test 4.5
4.5.2, object 3.2.1, operation 3.3, private type 7.4, qualified expression
4.7, record type 3.7, selected component 4.1.3, slice 4.1.2, subtype 3.3,
task type 9.1, type 3.3
> 3.9 Declarative Parts
A declarative part contains declarative items (possibly none).
declarative_part ::=
{basic_declarative_item} {later_declarative_item}
basic_declarative_item ::= basic_declaration
| representation_clause | use_clause
later_declarative_item ::= body
| subprogram_declaration | package_declaration
| task_declaration | generic_declaration
| use_clause | generic_instantiation
body ::= proper_body | body_stub
proper_body ::= subprogram_body | package_body | task_body
The elaboration of a declarative part consists of the elaboration of the
declarative items, if any, in the order in which they are given in the
declarative part. After its elaboration, a declarative item is said to be
elaborated. Prior to the completion of its elaboration (including before
the elaboration), the declarative item is not yet elaborated.
For several forms of declarative item, the language rules (in particular
scope and visibility rules) are such that it is either impossible or
illegal to use an entity before the elaboration of the declarative item
that declares this entity. For example, it is not possible to use the name
of a type for an object declaration if the corresponding type declaration
is not yet elaborated. In the case of bodies, the following checks are
performed:
- For a subprogram call, a check is made that the body of the subprogram
is already elaborated.
- For the activation of a task, a check is made that the body of the
corresponding task unit is already elaborated.
- For the instantiation of a generic unit that has a body, a check is
made that this body is already elaborated.
The exception PROGRAM_ERROR is raised if any of these checks fails.
If a subprogram declaration, a package declaration, a task declaration, or
a generic declaration is a declarative item of a given declarative part,
then the body (if there is one) of the program unit declared by the
declarative item must itself be a declarative item of this declarative part
(and must appear later). If the body is a body stub, then a separately
compiled subunit containing the corresponding proper body is required for
the program unit (see 10.2).
References: activation 9.3, instantiation 12.3, program_error exception
11.1, scope 8.2, subprogram call 6.4, type 3.3, visibility 8.3
Elaboration of declarations: 3.1, component declaration 3.7, deferred
constant declaration 7.4.3, discriminant specification 3.7.1, entry
declaration 9.5, enumeration literal specification 3.5.1, generic
declaration 12.1, generic instantiation 12.3, incomplete type declaration
3.8.1, loop parameter specification 5.5, number declaration 3.2.2, object
declaration 3.2.1, package declaration 7.2, parameter specification 6.1,
private type declaration 7.4.1, renaming declaration 8.5, subprogram
declaration 6.1, subtype declaration 3.3.2, task declaration 9.1, type
declaration 3.3.1
Elaboration of type definitions: 3.3.1, access type definition 3.8, array
type definition 3.6, derived type definition 3.4, enumeration type
definition 3.5.1, integer type definition 3.5.4, real type definition
3.5.6, record type definition 3.7
Elaboration of other constructs: context clause 10.1, body stub 10.2,
compilation unit 10.1, discriminant part 3.7.1, generic body 12.2, generic
formal parameter 12.1 12.3, library unit 10.5, package body 7.1,
representation clause 13.1, subprogram body 6.3, subunit 10.2, task body
9.1, task object 9.2, task specification 9.1, use clause 8.4, with clause
10.1.1